<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          社區(qū)精選|CSS 如何改變網(wǎng)格布局偶數(shù)行的排序?

          共 8816字,需瀏覽 18分鐘

           ·

          2023-09-08 03:07

          今天小編為大家?guī)?lái)的是社區(qū)作者 XboxYan 的文章,讓我們一起來(lái)學(xué)習(xí) CSS 改變網(wǎng)格布局偶數(shù)行的排序。




          最近在項(xiàng)目中看到這樣一個(gè)布局,如下:


          布局本身沒(méi)什么奇怪的,就是 4 * 2 的網(wǎng)格,比較特殊的是第二行布局是從右往左的,整體是一個(gè)這樣的順序


          而這個(gè)列表是通過(guò)一個(gè)數(shù)組動(dòng)態(tài)渲染的,可能有很多同學(xué)會(huì)將這個(gè)數(shù)組分成兩份,然后將第二份進(jìn)行反向,類似于這樣

          let arr1 = list.slice(0, 4)
          let arr2 = list.slice(4, 8).reverse()

          然后,由于第二行的第一個(gè)其實(shí)是原數(shù)組的第八個(gè),還需要針對(duì)第二行做額外的處理,比如序列

          // 第一行
          第 {{ i }} 個(gè)
          // 第二行
          第 {{ 8 - i } 個(gè)

          而且,如果有點(diǎn)擊事件,傳值也需要額外處理,雖然也能實(shí)現(xiàn),但顯然是太麻煩,而且還容易出 bug。

          那么,有沒(méi)有其他更簡(jiǎn)單、更穩(wěn)定的方式來(lái)解決呢?也就是如何讓第二行子項(xiàng)反向呢?


          一、flex 布局實(shí)現(xiàn)

          由于這里是動(dòng)態(tài)渲染,所以最理想的結(jié)構(gòu)應(yīng)該是這樣的,直接一層循環(huán)搞定

          <div class="list">
            <div class="item">1</div>
            <div class="item">2</div>
            <div class="item">3</div>
            <div class="item">4</div>
            <div class="item">5</div>
            <div class="item">6</div>
            <div class="item">7</div>
            <div class="item">8</div>
          </div>

          通過(guò) flex 或者 grid 都很容易實(shí)現(xiàn)4 * 2的布局,先用 flex 實(shí)現(xiàn)

          .list{
            display: flex;
            width: 600px;
            gap: 20px;
            flex-wrap: wrap;
          }
          .item{
            width: calc( (100% - 60px) / 4 );
            aspect-ratio: 1/1;
            background: royalblue;
            color: #fff;
            font-size: 30px;
            border-radius: 10px;
            display: flex;
            align-items: center;
            justify-content: center;
          }

          可以得到這樣的布局


          有什么辦法在不改變 html 的情況下改變第二行的位置呢???


          在 flex 中,可以直接通過(guò) order 進(jìn)行排序,order 越大,元素越靠后https://developer.mozilla.org/zh-CN/docs/Web/CSS/order


          比如,我們將第 5 個(gè)元素的order設(shè)置成1

          .item:nth-child(5){
            order: 1
          }

          由于默認(rèn)是 0,現(xiàn)在第 5 個(gè)元素的 order 最大,所以它跑到了最后面


          按照這樣的規(guī)則,我們可以將第 5、6、7、8 個(gè)子項(xiàng)的 order 分別一次減少就行了(大于 0 )

          .item:nth-child(5){
            order: 4;
          }
          .item:nth-child(6){
            order: 3;
          }
          .item:nth-child(7){
            order: 2;
          }
          .item:nth-child(8){
            order: 1;
          }

          這樣第二行就反向了,如下


          當(dāng)然還可以在循環(huán)的時(shí)候,加上 CSS 變量

          <div class="list">
            <div class="item" style="--i: 1">1</div>
            <div class="item" style="--i: 2">2</div>
            <div class="item" style="--i: 3">3</div>
            <div class="item" style="--i: 4">4</div>
            <div class="item" style="--i: 5">5</div>
            <div class="item" style="--i: 6">6</div>
            <div class="item" style="--i: 7">7</div>
            <div class="item" style="--i: 8">8</div>
          </div>

          然后可以用 calc 動(dòng)態(tài)去改變 order,如下

          .item:nth-child(n + 5){
            order: calc( 8 - var(--i))
          }

          同樣能達(dá)到相同的效果,完整代碼可以查看


          • https://codepen.io/xboxyan/pen/bGQPmpO


          二、grid 布局實(shí)現(xiàn)

          還是同樣的布局,現(xiàn)在換 grid 實(shí)現(xiàn),正常情況下,可能會(huì)直接用 repeat(4, 1fr)來(lái)實(shí)現(xiàn)一個(gè) 4 * 2 的布局

          .list{
            display: grid;
            width: 600px;
            gap: 20px;
            grid-template-columns: repeat(4, 1fr);
          }
          .item{
            aspect-ratio: 1/1;
            background: royalblue;
            color: #fff;
            font-size: 30px;
            border-radius: 10px;
            display: flex;
            align-items: center;
            justify-content: center;
          }

          效果如下


          那么,如何讓下面一行反過(guò)來(lái)呢?

          除了使用上面的方式,還可以用帶有名稱的grid-template-areas來(lái)實(shí)現(xiàn),比如我們這樣命名

          .list{
            /**/
            grid-template-areas: 
              'a1 a2 a3 a4'
              'a5 a6 a7 a8';
          }

          這樣就劃分成了 a1~a8 一共八塊區(qū)域,為了方便映射,我們可以在生成 html 時(shí),通過(guò) CSS 變量帶上這些名稱

          <div class="list">
            <div class="item" style="--i: a1">1</div>
            <div class="item" style="--i: a2">2</div>
            <div class="item" style="--i: a3">3</div>
            <div class="item" style="--i: a4">4</div>
            <div class="item" style="--i: a5">5</div>
            <div class="item" style="--i: a6">6</div>
            <div class="item" style="--i: a7">7</div>
            <div class="item" style="--i: a8">8</div>
          </div>

          這樣就可以很方便的把每一個(gè)子項(xiàng)“填入”對(duì)應(yīng)的區(qū)域了

          .item{
            /**/
            grid-area: var(--i);
          }

          現(xiàn)在仍然是默認(rèn)順序,如果要改變第二行的順序,直接 grid-template-areas 就行了

          .list{
            /**/
            grid-template-areas: 
              'a1 a2 a3 a4'
              'a8 a7 a6 a5'; /* 把第二行反向 */
          }

          這樣就很方便直觀的改變了子項(xiàng)的位置了,效果如下


          完整代碼可以查看

          • https://codepen.io/xboxyan/pen/NWEZOyZ


          三、更加靈活的“蛇形布局”

          上面的例子只有兩行,如果有多行呢,并且行數(shù)不定,如何處理呢?就像這樣的


          這種時(shí)候用 grid 可能少許不方便了(可能我還沒(méi)找到精髓??),下面用 flex 實(shí)現(xiàn)


          目前 CSS 中并沒(méi)有能夠檢測(cè)第幾行的選擇器,所以只能用其他方式。假設(shè)每一行的個(gè)數(shù)是確定的,這里是 4,那么,第二行就是5678,隔一行,第四行就是 13141516,依次類推。


          有什么方式可以匹配第幾個(gè)呢?沒(méi)錯(cuò),就是:nth-child,由于是隔一行,所以是每 8 個(gè)一個(gè)循環(huán),可以這樣來(lái)選擇偶數(shù)行,如下

          .item:nth-child(8n + 5){
            /*選擇第5、13、21...*/
          }
          .item:nth-child(8n + 6){
            /*選擇第6、14、22...*/
          }
          .item:nth-child(8n + 7){
            /*選擇第7、15、23...*/
          }
          .item:nth-child(8n + 8){
            /*選擇第8、16、24...*/
          }

          由于默認(rèn)的 orde r是 0,如果改變其他的 order 肯定會(huì)跑到后面去,為了避免影響,可以先手動(dòng)設(shè)置 order

          .item{
            /**/
            order: var(--i);
          }

          下面要對(duì)偶數(shù)行的順序進(jìn)行調(diào)整,比如第二行


          第 1 個(gè)的位置調(diào)到第 4 個(gè)位置,所以 order 需要加 3

          第 2 個(gè)的位置調(diào)到第 3 個(gè)位置,所以 order 需要加 1

          第 3 個(gè)的位置調(diào)到第 2 個(gè)位置,所以 order 需要減 1

          第 4 個(gè)的位置調(diào)到第 1 個(gè)位置,所以 order 需要減 3


          最后實(shí)現(xiàn)就是

          .item:nth-child(8n + 5){
            order: calc(var(--i) + 3)
          }
          .item:nth-child(8n + 6){
            order: calc(var(--i) + 1)
          }
          .item:nth-child(8n + 7){
            order: calc(var(--i) - 1)
          }
          .item:nth-child(8n + 8){
            order: calc(var(--i) - 3)
          }

          這樣就實(shí)現(xiàn)了行數(shù)不固定的“蛇形布局”,完整代碼如下:

          https://codepen.io/xboxyan/pen/YzRoBNY


          四、優(yōu)勢(shì)和總結(jié)

          這樣實(shí)現(xiàn)有什么優(yōu)勢(shì)呢?很明顯 JavaScript 無(wú)需關(guān)注布局,只用處理業(yè)務(wù)邏輯就行,也無(wú)需單獨(dú)對(duì)第二行元素做特殊處理,特別是序列,之前很容易混亂,最重要的是實(shí)現(xiàn)更加清晰明了,也更加穩(wěn)定。下面總結(jié)一下要點(diǎn)


          1. 用 js 來(lái)修改布局比較麻煩,而且邏輯容易混亂

          2. flex 中可以用 order 來(lái)改變子項(xiàng)位置

          3. 借助 CSS 變量可以更加方便地映射到每個(gè)子項(xiàng)

          4. grid 中可以用 grid-template-areas 手動(dòng)指定每個(gè)子項(xiàng)的位置

          5. 蛇形布局可以用 nth-child 選中偶數(shù)項(xiàng),從而改變位置

          按照我的經(jīng)驗(yàn),布局最好 CSS 單獨(dú)完成,不要讓 JS 參與其中,這樣邏輯也會(huì)更加清晰。最后,如果覺(jué)得還不錯(cuò),對(duì)你有幫助的話,歡迎點(diǎn)贊、收藏、轉(zhuǎn)發(fā)???



          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開(kāi)更多互動(dòng)和交流,公眾號(hào)后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -



          往期推薦


          社區(qū)精選|Spring 中 @Qualifier 注解還能這么用?


          社區(qū)精選|【動(dòng)畫進(jìn)階】有意思的 Emoji 3D 表情切換效果


          社區(qū)精選|【NestJS 系列】DI 依賴注入與 IOC 控制反轉(zhuǎn)






          瀏覽 192
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人艹| 日本国产操逼网 | 黄色片网站视频 | 国产91 白丝在线播放 | 婷婷丁香综合网 |