最近在項目中碰到這樣一個布局,有一個列表,先按照 4 * 2 的正常順序排列,當超過 8 個后,會橫向重新開始 4 * 2 的布局,有點像一個個獨立的分組,然后水平排列,如下
圖中序號是 dom 序列,所以其實這這樣的一個順序。
很多同學可能會想到給子元素分組(通過 JS
將原數組拆分組合成一個二維數組),每 8 個套一層容器,然后水平排列就行了
是不是有點麻煩呢?
其實,無需單獨嵌套容器也能實現類似分組的效果,這就需要借助本文要介紹的 column 布局了,一起看看吧~
平時接觸較多的都是flex或者grid,但還有一個columns布局往往被忽視了。
https://developer.mozilla.org/zh-CN/docs/Web/CSS/columns
columns布局,又稱“多列”布局(或者“分欄”布局),這是一個使用場景比較有限,但是幾乎無法被替代的一種布局。
使用非常簡單,直接看一個例子,假設有這樣一段文本
p{ width: 500px;}
<p>歡迎關注前端偵探,這里有一些有趣的、你可能不知道的HTML、CSS、JS小技巧技巧,比如這篇文章,如何使用 CSS columns 布局來實現自動分組布局,一起看看吧</p>
默認是這樣的。
下面我們將段文本分成3列。
p{ columns: 3;}
看,自動就分成了3列。
并且閱讀順序是從左到右,從下到下,直到整列閱讀完成,非常類似以前的報刊讀物閱讀習慣。
除了指定列數,還可以根據指定寬度自動去計算列數,比如:
p{ columns: 100px;}
效果如下:
這個表示按照最小100px去分段,看最多可以分成多少列,并不是說每列就一定是 100,應該是大于等于 100,直到剩余空間可以再放下一列。
那為啥設置的是100,總寬度是500,卻只分成了4列?原因是有「默認列間距」,如果去除這個間距。
p{ column-gap: 0px;}
這樣就剛好被分成了5列。
看不清楚?加個分割線試試。
p{ column-rule: 1px solid red;}
是不是剛好分成了 5 列?(注意,這里的分割線是不占空間的)。
簡單了解columns多列布局后,下面來看另外的用途。
可能你已經發現了,上面的文本分列布局和我們文章開頭所需要的效果非常類似,都是一列一列的,因此我們可以嘗試用columns布局來實現這樣的效果。
假設html是這樣的。
<div class="wrap"> <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 class="item">9</div> <div class="item">10</div> <div class="item">11</div> <div class="item">12</div> <div class="item">13</div> <div class="item">14</div> </div></div>
這里多了一層wrap是用來做滾動容器的,簡單修飾一下。
.wrap{ display: flex; width: 400px; overflow: auto; outline: 1px dashed #9747FF;}.item{ display: inline-flex; width: 80px; margin: 10px; aspect-ratio: 1/1; background: #FFE8A3; color: #333; font-size: 30px; border-radius: 10px; align-items: center; justify-content: center;}
效果如下,很正常的一個布局。
現在,我們希望縱向高度是固定的,然后橫向滾動,先加一個高度試試。
.list{ height: 200px;}
這樣就變成了縱向滾動的布局了。
那么,如何讓它橫向分欄并且滾動呢?其實非常簡單,只需要添加一行。
.list{ height: 200px; column-width: 400px;}
設置分欄寬度為滾動容器寬度之后,就自動將整個列表分成多組了,相當于每個滾動屏幕作為一組,從左到右排列,由于空間不足,所以可以橫向滾動。
是不是非常神奇?僅需一個屬性就實現了縱向滾動到橫向滾動的切換。
通常碰到這種橫向滾動的效果,你可能會想到一個swiper組件,也就是那種一屏一屏切換的效果,沒錯,我們這里也可以借助scroll-snap輕易實現。
關于scroll-snap,網上教程非常多,MDN 官網也有非常清晰的 demo,如果不熟悉的可以先去了解一下:https://developer.mozilla.org/zh-CN/docs/Web/CSS/scroll-snap-type。
這里就不詳細介紹了。
回到這里,由于整個列表下面只有一層子元素,好像并沒有辦法區分每一屏的臨界點。其實不然,可以想一下,這里每一屏有 8 個元素,也就是第1、9、17...個分別是每一屏的第一個元素,是不是可以以這些元素為標識(吸附對象)呢?
首先要在滾動容器下定義一下。
.wrap{ scroll-snap-type: x mandatory;}
然后給第1、9、17...個元素添加吸附對象,這里可以用nth-child選擇器。
.item:nth-child(8n+1){ scroll-snap-align: start;}
效果如下(為了區分,把每一屏的第一個元素背景做了高亮)。
還可以多添加點元素,多切幾屏看看效果:
完整代碼可以參考:
相對于傳統的 JS實現來說,有哪些好處呢?
有這么多好處還不趕緊用起來?下面再來回顧一下columns布局。
多想象一下,其實可以有更多的使用場景,雖然本來并不是做這個事情的。
[1]CSS columns (juejin.cn): https://code.juejin.cn/pen/7293927297596260379。
[2]CSS column (codepen.io): https://codepen.io/xboxyan/pen/RwvPLEM。
本文鏈接:http://www.tebozhan.com/showinfo-26-15891-0.html使用 CSS Columns 布局來實現自動分組布局
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com