你肯定會(huì)用到的CSS多行多列布局
前言:因?yàn)轫?xiàng)目中使用flex過(guò)程中,如果采用space-between兩端對(duì)齊,會(huì)遇到最后一行難以對(duì)齊的問(wèn)題。本文主要對(duì)多行多列這種常見(jiàn)的布局,列出解決方案,方便大家日常開(kāi)發(fā)使用。
話(huà)不多說(shuō),直接進(jìn)入正題:
方案一:標(biāo)簽補(bǔ)位
我們都知道,之所以對(duì)不齊是因?yàn)樽詈笠恍械淖禹?xiàng)目沒(méi)有達(dá)到4個(gè),space-between的對(duì)齊方式,自然會(huì)把中間空出來(lái)。既然如此,何不直接補(bǔ)位,讓元素排滿(mǎn)4個(gè)。
- <!-- 樣式 -->
- <style>
- .list{
- display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
- }
- .item{
- /* flex: 0 0 24% 該屬性等價(jià)于 flex:none;width:24% */
- flex: 0 0 24%;
- height: 100px;
- background-color: aqua;
- margin-bottom: 10px;
- }
- .item-fill{
- flex: 0 0 24%;
- height:0;
- }
- /* 消除最后一行多余邊距 */
- .list .item:nth-last-child(-n+4){
- margin-bottom: 0;
- }
- </style>
- <!-- html -->
- <div class="list">
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item-fill"></div>
- <div class="item-fill"></div>
- <div class="item-fill"></div>
- </div>
效果如下:
如果子元素個(gè)數(shù)不是4個(gè)怎么辦?我們細(xì)心觀(guān)察,不難發(fā)現(xiàn),最后一行的最小值是1個(gè),那么我們只需要補(bǔ)位n-1個(gè)即可。如果只有3個(gè),也可以用偽元素::after去補(bǔ)最后一個(gè)位置。
方案二:計(jì)算剩余空間
如果我們知道最后一行剩余空間的話(huà),完全可以控制最后一個(gè)元素的邊距或者縮放比例去占滿(mǎn)剩下的空間,自然就能左對(duì)齊了。要做到這一點(diǎn),首先得確定寬度和邊距,寬度通常是已知的,我們只需要把邊距確定下來(lái),就能確認(rèn)剩余空間。
接上面的的例子,假設(shè)一行有4個(gè), 每個(gè)占比24%,4個(gè)就是24% * 4 = 96% , 那么可以確定總邊距是4%,由于一行有4個(gè)元素,而最后一個(gè)的右邊距是多余的,那么可以確定單個(gè)的邊距為 4% / 3 = 1.333% , 計(jì)算出來(lái)后就可以開(kāi)始寫(xiě)代碼了:
- <!-- css -->
- <style>
- .list{
- display: flex;
- justify-content: space-between;
- flex-wrap: wrap;
- }
- .item{
- flex: 0 0 24%;
- height: 100px;
- background-color: aqua;
- /* 邊距懶得算,css函數(shù)代替 */
- margin-right: calc(4% / 3);
- margin-bottom: calc(4% / 3);
- }
- /* 去除每行尾的多余邊距 */
- .item:nth-child(4n){
- margin-right: 0;
- }
- /* 使最后一個(gè)元素的邊距填滿(mǎn)剩余空間 */
- .item:last-child{
- margin-right: auto;
- }
- /* 也可以給列表增加一個(gè)占位元素,自動(dòng)縮放填滿(mǎn)剩余空間 */
- /* .list::after{
- content: '';
- flex: 1;
- height: 0;
- } */
- .list .item:nth-last-child(-n+4){
- margin-bottom: 0;
- }
- </style>
- <!-- html -->
- <div class="list">
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- </div>
效果如下:
可能有些小伙伴覺(jué)得懶得記,那么下面直接給出封裝好的sass mixin, 復(fù)制即可使用:
- /**
- * 多列布局
- * $count 項(xiàng)目數(shù)量
- * $itemWidth 項(xiàng)目寬度,百分比,不含百分號(hào)
- * $itemHeight 項(xiàng)目高度,隨意
- */
- @mixin grid($count:4, $itemWidth:20, $itemHeight:auto) {
- $rest: 100 - $itemWidth * $count; // 剩余空間
- $space: percentage($rest/($count - 1)/100); // 邊距
- display: flex;
- flex-wrap: wrap;
- /*此處的*號(hào)建議替換成具體的布局容器(div,view...),以加快css解析*/
- & > * {
- flex: 0 0 #{$itemWidth + '%'};
- height: $itemHeight;
- margin-right: $space;
- margin-bottom: $space;
- box-sizing: border-box;
- &:nth-child(#{$count}n) {
- margin-right: 0;
- }
- &:nth-last-child(-n + #{$count}) {
- margin-bottom: 0;
- }
- /*為了兼容space-between的布局,占滿(mǎn)剩余空間*/
- &:last-child {
- margin-right: auto;
- }
- }
- }
- /*使用方法*/
- .list{
- /* 一行4項(xiàng),每項(xiàng)20%寬度 */
- @include grid(4,20)
- }
以上為flex版本,假如你需要兼容ie瀏覽器,那么可以用float布局替換,float自動(dòng)左對(duì)齊,也就不需要填充最后的剩余空間了。
方案三:網(wǎng)格布局
網(wǎng)格布局,默認(rèn)就是左對(duì)齊,即使使用space-between。
- <style>
- .list {
- display: grid;
- justify-content: space-between;
- grid-template-columns: 1fr 1fr 1fr 1fr; /*設(shè)置等比列*/
- gap: 10px; /*行間距*/
- }
- .item{
- background-color: aqua;
- height: 100px;
- }
- </style>
- <!-- html -->
- <div class="list">
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- <div class="item"></div>
- </div>
效果如下:
上面的三個(gè)方案各有各的好處:
- 方案一的缺點(diǎn)是實(shí)現(xiàn)不夠優(yōu)雅,需要增加無(wú)用的占位標(biāo)簽。
- 方案二倒沒(méi)什么缺點(diǎn),除了寫(xiě)法會(huì)復(fù)雜點(diǎn),但只要封裝好mixin在sass中使用足夠簡(jiǎn)單,即使需要兼容ie,也只需要換成float即可。
- 方案三,兼容性最差,無(wú)法在ie中正常使用,但用法最簡(jiǎn)單,布局甚至比f(wàn)lex還要強(qiáng)大。
綜上,實(shí)際使用中,還是推薦使用方案二。