【推荐好文章:@XboxYan】 最近在项目中看到这样一个布局,如下
布局本身没什么古怪的,便是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>
经过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;
}
能够得到这样的布局
有什么办法在不改动 html 的情况下改动第二行的方位呢?
在 flex 中,能够直接经过 order 进行排序,order 越大,元素越靠后。
developer.mozilla.org/zh-CN/docs/…
比方,咱们将第 5 个元素的 order 设置成 1
.item:nth-child(5){
order: 1
}
因为默认是 0,现在第 5 个元素的 order 最大,所以它跑到了最后面
依照这样的规矩,咱们能够将第 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;
}
这样第二行就反向了,如下
<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))
}
相同能达到相同的效果,完好代码能够检查:codepen.io/xboxyan/pen…
二、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;
}
效果如下
那么,怎么让下面一行反过来呢?
除了运用上面的方法,还能够用带有称号的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'; /* 把第二行反向 */
}
这样就很便利直观的改动了子项的方位了,效果如下
完好代码能够检查:codepen.io/xboxyan/pen…
三、愈加灵活的 “蛇形布局”
上面的例子只有两行,如果有多行呢,并且行数不定,怎么处理呢?就像这样的
这种时候用 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);
}
下面要对偶数行的次序进行调整,比方第二行
第 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)
}
这样就完成了行数不固定的 “蛇形布局”,完好代码如下:codepen.io/xboxyan/pen…
四、优势和总结
这样完成有什么优势呢?很明显 JavaScript 无需重视布局,只用处理事务逻辑就行,也无需独自对第二行元素做特别处理,特别是序列,之前很简单紊乱,最重要的是完成愈加清晰明了,也愈加安稳。下面总结一下关键
- 用 js 来修正布局比较费事,并且逻辑简单紊乱
- flex 中能够用 order 来改动子项方位
- 借助 CSS 变量能够愈加便利地映射到每个子项
- grid 中能够用
grid-template-areas
手动指定每个子项的方位 - 蛇形布局能够用
nth-child
选中偶数项,从而改动方位