CSS 如何改变网格布局偶数行的排序?
当前位置:点晴教程→知识管理交流
→『 技术文档交流 』
最近在项目中看到这样一个布局,如下 布局本身没什么奇怪的,就是 4 * 2 的网格,比较特殊的是第二行布局是从右往左的,整体是一个这样的顺序 而这个列表是通过一个数组动态渲染的,可能有很多同学会将这个数组分成两份,然后将第二份进行反向,类似于这样 let arr1 = list.slice(0, 4) let arr2 = list.slice(4, 8).reverse() 然后,由于第二行的第一个其实是原数组的第八个,还需要针对第二行做额外的处理,比如序列 // 第一行 第 {{ i }} 个 // 第二行 第 {{ 8 - i }} 个 而且,如果有点击事件,传值也需要额外处理,虽然也能实现,但显然是太麻烦,而且还容易出 bug。 那么,有没有其他更简单、更稳定的方式来解决呢?也就是如何让第二行子项反向呢? 一、flex 布局实现由于这里是动态渲染,所以最理想的结构应该是这样的,直接一层循环搞定 <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> 通过 .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; } 可以得到这样的布局 有什么办法在不改变 在 https://developer.mozilla.org/zh-CN/docs/Web/CSS/order 比如,我们将第 5 个元素的 .item:nth-child(5){ order: 1} 由于默认是 按照这样的规则,我们可以将第 5、6、7、8 个子项的 .item:nth-child(5){ order: 4; } .item:nth-child(6){ order: 3; } .item:nth-child(7){ order: 2; } .item:nth-child(8){ order: 1; } 这样第二行就反向了,如下 当然还可以在循环的时候,加上 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动态去改变 .item:nth-child(n + 5){ order: calc( 8 - var(--i)) } 同样能达到相同的效果,完整代码可以查看 二、grid 布局实现还是同样的布局,现在换 grid 实现,正常情况下,可能会直接用 .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; } 效果如下 那么,如何让下面一行反过来呢? 除了使用上面的方式,还可以用带有名称的 .list{ /**/ grid-template-areas: 'a1 a2 a3 a4' 'a5 a6 a7 a8'; } 这样就划分成了 <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> 这样就可以很方便的把每一个子项“填入”对应的区域了 .item{ /**/ grid-area: var(--i); } 现在仍然是默认顺序,如果要改变第二行的顺序,直接 .list{ /**/ grid-template-areas: 'a1 a2 a3 a4' 'a8 a7 a6 a5'; /* 把第二行反向 */} 这样就很方便直观的改变了子项的位置了,效果如下 完整代码可以查看 三、更加灵活的“蛇形布局”上面的例子只有两行,如果有多行呢,并且行数不定,如何处理呢?就像这样的 这种时候用 grid 可能少许不方便了(可能我还没找到精髓😂),下面用 flex 实现 目前 CSS 中并没有能够检测第几行的选择器,所以只能用其他方式。假设每一行的个数是确定的,这里是 有什么方式可以匹配第几个呢?没错,就是 .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...*/ } 由于默认的 .item{ /**/ order: var(--i); } 下面要对偶数行的顺序进行调整,比如第二行 第 1 个的位置调到第4个位置,所以 第 2 个的位置调到第3个位置,所以 第 3 个的位置调到第2个位置,所以 第 4 个的位置调到第1个位置,所以 最后实现就是 .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) } 这样就实现了行数不固定的“蛇形布局”,完整代码如下 四、优势和总结这样实现有什么优势呢?很明显 Javascript 无需关注布局,只用处理业务逻辑就行,也无需单独对第二行元素做特殊处理,特别是序列,之前很容易混乱,最重要的是实现更加清晰明了,也更加稳定。下面总结一下要点
按照我的经验,布局最好 CSS 单独完成,不要让 JS 参与其中,这样逻辑也会更加清晰。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤ 该文章在 2023/8/26 10:40:34 编辑过 |
关键字查询
相关文章
正在查询... |