使用CSS 怎么改网格布局上下行的顺序

简介: Flex 布局是一种简单而灵活的布局方式,通过设置父容器的 display: flex 属性,可以方便地控制子元素的排列方式、对齐和间距等。它适用于一维排列的情况,比如横向或纵向的列表、导航栏等。Grid 布局则是一种更为复杂的布局方式,可以将网页划分为等大小的网格,并通过设置网格的属性来定义子元素的位置。它适用于二维排列的情况,比如网格状的图像展示、多列的表格等。

最近在项目中看到这样一个布局,如下

image.png

布局本身没什么奇怪的,就是 4 * 2 的网格,比较特殊的是第二行布局是从右往左的,整体是一个这样的顺序

image.png

而这个列表是通过一个数组动态渲染的,可能有很多同学会将这个数组分成两份,然后将第二份进行反向,类似于这样

 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>

通过 flex 或者 grid 都很容易实现 4 * 2 的布局,先用 flex 实现

 .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;
 }

可以得到这样的布局

image.png

有什么办法在不改变 html 的情况下改变第二行的位置呢?🤔

在 flex 中,可以直接通过 order 进行排序,order 越大,元素越靠后。

https://developer.mozilla.org/zh-CN/docs/Web/CSS/order

比如,我们将第 5 个元素的 order 设置成 1

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

由于默认是 0,现在第 5 个元素的 order 最大,所以它跑到了最后面

image.png

按照这样的规则,我们可以将第 5、6、7、8 个子项的 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;
 }

这样第二行就反向了,如下
image.png

当然还可以在循环的时候,加上 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 动态去改变 order,如下

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

同样能达到相同的效果,完整代码可以查看:https://codepen.io/xboxyan/pen/bGQPmpO

二、grid 布局实现

还是同样的布局,现在换 grid 实现,正常情况下,可能会直接用 repeat(4, 1fr) 来实现一个 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;
 }

效果如下

image.png

那么,如何让下面一行反过来呢?

除了使用上面的方式,还可以用带有名称的 grid-template-areas 来实现,比如我们这样命名

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

这样就划分成了 a1~a8 一共八块区域,为了方便映射,我们可以在生成 html 时,通过 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>

这样就可以很方便的把每一个子项 “填入” 对应的区域了

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

现在仍然是默认顺序,如果要改变第二行的顺序,直接 grid-template-areas 就行了

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

这样就很方便直观的改变了子项的位置了,效果如下

image.png

完整代码可以查看:https://codepen.io/xboxyan/pen/NWEZOyZ

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

上面的例子只有两行,如果有多行呢,并且行数不定,如何处理呢?就像这样的

image.png

这种时候用 grid 可能少许不方便了(可能我还没找到精髓😂),下面用 flex 实现

目前 CSS 中并没有能够检测第几行的选择器,所以只能用其他方式。假设每一行的个数是确定的,这里是 4,那么,第二行就是 5、6、7、8,隔一行,第四行就是 13、14、15、16,依次类推。

有什么方式可以匹配第几个呢?没错,就是:nth-child,由于是隔一行,所以是每 8 个一个循环,可以这样来选择偶数行,如下

 .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...*/
 }

由于默认的 order 是 0,如果改变其他的 order 肯定会跑到后面去,为了避免影响,可以先手动设置 order

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

下面要对偶数行的顺序进行调整,比如第二行

image.png
第 1 个的位置调到第 4 个位置,所以 order 需要加 3

第 2 个的位置调到第 3 个位置,所以 order 需要加 1

第 3 个的位置调到第 2 个位置,所以 order 需要减 1

第 4 个的位置调到第 1 个位置,所以 order 需要减 3

最后实现就是

 .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)
 }

这样就实现了行数不固定的 “蛇形布局”,完整代码如下:https://codepen.io/xboxyan/pen/YzRoBNY

四、优势和总结

这样实现有什么优势呢?很明显 JavaScript 无需关注布局,只用处理业务逻辑就行,也无需单独对第二行元素做特殊处理,特别是序列,之前很容易混乱,最重要的是实现更加清晰明了,也更加稳定。下面总结一下要点

  • 用 js 来修改布局比较麻烦,而且逻辑容易混乱
  • flex 中可以用 order 来改变子项位置
  • 借助 CSS 变量可以更加方便地映射到每个子项
  • grid 中可以用 grid-template-areas 手动指定每个子项的位置
  • 蛇形布局可以用 nth-child 选中偶数项,从而改变位置
相关文章
|
6天前
|
前端开发 容器
css布局-弹性布局学习笔记
这篇文章是关于CSS弹性布局的学习笔记,详细介绍了flex容器和元素的相关属性,包括flex-direction、flex-wrap、flex-flow、justify-content、align-items、align-content以及order、flex-grow、flex-shrink、flex-basis、flex和align-self等,解释了这些属性在弹性盒子布局中的作用和用法。
|
6天前
|
JavaScript 前端开发
网页前端课程设计-【模仿】香港中文大学官网,轮播图及div+css布局,js的dom操作
这篇文章介绍了如何模仿香港中文大学官网进行网页前端课程设计,包括使用div+css布局、js的DOM操作以及实现轮播图等技术细节。
|
2月前
|
前端开发 安全 容器
CSS如何优雅实现卡片多行排列布局?
【8月更文挑战第24天】CSS如何优雅实现卡片多行排列布局?
42 3
|
2月前
|
前端开发 开发者 容器
探索现代Web开发中的CSS Grid布局技术
【8月更文挑战第29天】在数字时代的浪潮中,网页设计不断进化以适应日新月异的用户需求。CSS Grid布局技术作为一项革新性的前端工具,为设计师和开发者提供了前所未有的布局能力。本文旨在通过深入浅出的方式介绍CSS Grid的核心概念、基本用法以及在实际项目中的应用,帮助读者快速掌握这一强大的网页布局工具。
41 3
|
2月前
|
前端开发 开发者 容器
【Web布局的革命】探索CSS Grid栅格系统,打造未来网页设计!
【8月更文挑战第25天】在网页设计领域,布局至关重要。传统的布局方法难以满足复杂需求,CSS Grid 栅格系统因此诞生。它是一种二维布局模式,能直接控制行和列,简化复杂网格的设计。通过定义 `display: grid;` 创建网格容器,并利用 `grid-template-columns` 和 `grid-template-rows` 设置行列尺寸,轻松实现响应式布局。此外,CSS Grid 支持高级功能,如网格区域划分和对齐设置,极大提升了布局的灵活性和创意空间。随着浏览器兼容性的增强,CSS Grid 必将成为未来网页设计的关键技术之一。
52 1
|
2月前
|
前端开发 JavaScript Serverless
揭秘CSS布局神器:vw/vh、rem、%与px大PK,掌握它们,让你的网页设计秒变高大上,面试难题迎刃而解!
【8月更文挑战第4天】在Web开发中,合理选择CSS单位对响应式布局至关重要。本文探索viewport单位(vw/vh)、rem、百分比(%)及像素(px)的基础知识与应用场景。通过代码示例,展示如何运用这些单位实现全屏布局、尺寸比例调整、灵活的元素大小及固定尺寸。最后,模拟面试题,介绍如何仅用CSS实现一个元素的高度为其宽度两倍且响应视口变化的方法。
161 8
|
2月前
|
前端开发
CSS Grid 布局:span 关键字
CSS Grid 布局:span 关键字
40 0
|
2月前
|
前端开发 容器
css中弹性布局使用方法
css中弹性布局使用方法
37 0
|
2月前
|
编解码 前端开发 容器
CSS弹性布局:打造响应式与灵活的网页设计
CSS弹性布局:打造响应式与灵活的网页设计
76 0
|
3月前
|
编解码 前端开发 容器
CSS Flex布局实战案例:构建响应式卡片组件
【7月更文挑战第17天】通过上述步骤,我们成功地使用CSS Flex布局构建了一个响应式的卡片组件。Flexbox不仅简化了布局代码,还让我们能够轻松实现复杂的布局效果,如响应式设计。在实战中,掌握Flexbox将大大提高前端开发的效率和网页布局的质量。希望这个案例能够帮助你更好地理解和应用Flexbox布局。