注册/登录

你肯定会用到的CSS多行多列布局

开发 前端
因为项目中使用flex过程中,如果采用space-between两端对齐,会遇到最后一行难以对齐的问题。本文主要对多行多列这种常见的布局,列出解决方案,方便大家日常开发使用。

前言:因为项目中使用flex过程中,如果采用space-between两端对齐,会遇到最后一行难以对齐的问题。本文主要对多行多列这种常见的布局,列出解决方案,方便大家日常开发使用。

话不多说,直接进入正题:

方案一:标签补位
我们都知道,之所以对不齐是因为最后一行的子项目没有达到4个,space-between的对齐方式,自然会把中间空出来。既然如此,何不直接补位,让元素排满4个。

  1. <!-- 样式 --> 
  2. <style> 
  3.     .list{ 
  4.         display: flex; 
  5.         justify-content: space-between
  6.         flex-wrap: wrap; 
  7.     } 
  8.     .item{ 
  9.         /* flex: 0 0 24% 该属性等价于 flex:none;width:24% */ 
  10.         flex: 0 0 24%; 
  11.         height: 100px; 
  12.         background-color: aqua; 
  13.         margin-bottom: 10px; 
  14.     } 
  15.     .item-fill{ 
  16.         flex: 0 0 24%; 
  17.         height:0; 
  18.     } 
  19.     /* 消除最后一行多余边距 */ 
  20.     .list .item:nth-last-child(-n+4){ 
  21.         margin-bottom: 0; 
  22.     } 
  23. </style> 
  24.  
  25. <!-- html --> 
  26. <div class="list"
  27.     <div class="item"></div> 
  28.     <div class="item"></div> 
  29.     <div class="item"></div> 
  30.     <div class="item"></div> 
  31.     <div class="item"></div> 
  32.     <div class="item"></div> 
  33.  
  34.     <div class="item-fill"></div> 
  35.     <div class="item-fill"></div> 
  36.     <div class="item-fill"></div> 
  37. </div> 

效果如下:

如果子元素个数不是4个怎么办?我们细心观察,不难发现,最后一行的最小值是1个,那么我们只需要补位n-1个即可。如果只有3个,也可以用伪元素::after去补最后一个位置。

方案二:计算剩余空间
如果我们知道最后一行剩余空间的话,完全可以控制最后一个元素的边距或者缩放比例去占满剩下的空间,自然就能左对齐了。要做到这一点,首先得确定宽度和边距,宽度通常是已知的,我们只需要把边距确定下来,就能确认剩余空间。

接上面的的例子,假设一行有4个, 每个占比24%,4个就是24% * 4 = 96% , 那么可以确定总边距是4%,由于一行有4个元素,而最后一个的右边距是多余的,那么可以确定单个的边距为 4% / 3 = 1.333% , 计算出来后就可以开始写代码了:

  1. <!-- css --> 
  2. <style> 
  3.     .list{ 
  4.         display: flex; 
  5.         justify-content: space-between
  6.         flex-wrap: wrap; 
  7.     } 
  8.     .item{ 
  9.         flex: 0 0 24%; 
  10.         height: 100px; 
  11.         background-color: aqua; 
  12.         /* 边距懒得算,css函数代替 */ 
  13.         margin-right: calc(4% / 3); 
  14.         margin-bottom: calc(4% / 3); 
  15.     } 
  16.     /* 去除每行尾的多余边距 */ 
  17.     .item:nth-child(4n){ 
  18.         margin-right: 0; 
  19.     } 
  20.     /* 使最后一个元素的边距填满剩余空间 */ 
  21.     .item:last-child{ 
  22.         margin-right: auto; 
  23.     } 
  24.     /* 也可以给列表增加一个占位元素,自动缩放填满剩余空间 */ 
  25.     /* .list::after
  26.         content: ''
  27.         flex: 1; 
  28.         height: 0; 
  29.     } */ 
  30.     .list .item:nth-last-child(-n+4){ 
  31.         margin-bottom: 0; 
  32.     } 
  33. </style> 
  34. <!-- html --> 
  35. <div class="list"
  36.     <div class="item"></div> 
  37.     <div class="item"></div> 
  38.     <div class="item"></div> 
  39.     <div class="item"></div> 
  40.     <div class="item"></div> 
  41.     <div class="item"></div> 
  42. </div> 

效果如下:

可能有些小伙伴觉得懒得记,那么下面直接给出封装好的sass mixin, 复制即可使用:

  1. /** 
  2.  * 多列布局 
  3.  * $count 项目数量 
  4.  * $itemWidth 项目宽度,百分比,不含百分号 
  5.  * $itemHeight 项目高度,随意 
  6.  */ 
  7. @mixin grid($count:4, $itemWidth:20, $itemHeight:auto) { 
  8.     $rest: 100 - $itemWidth * $count; // 剩余空间 
  9.     $space: percentage($rest/($count - 1)/100); // 边距 
  10.     display: flex; 
  11.     flex-wrap: wrap; 
  12.  
  13.     /*此处的*号建议替换成具体的布局容器(div,view...),以加快css解析*/ 
  14.     & > * { 
  15.         flex: 0 0 #{$itemWidth + '%'}; 
  16.         height: $itemHeight; 
  17.         margin-right: $space
  18.         margin-bottom: $space
  19.         box-sizing: border-box; 
  20.  
  21.         &:nth-child(#{$count}n) { 
  22.             margin-right: 0; 
  23.         } 
  24.  
  25.         &:nth-last-child(-n + #{$count}) { 
  26.             margin-bottom: 0; 
  27.         } 
  28.  
  29.         /*为了兼容space-between的布局,占满剩余空间*/ 
  30.         &:last-child { 
  31.             margin-right: auto; 
  32.         } 
  33.     } 
  34.  
  35. /*使用方法*/ 
  36. .list{ 
  37.     /* 一行4项,每项20%宽度 */ 
  38.     @include grid(4,20) 

以上为flex版本,假如你需要兼容ie浏览器,那么可以用float布局替换,float自动左对齐,也就不需要填充最后的剩余空间了。

方案三:网格布局
网格布局,默认就是左对齐,即使使用space-between。

  1. <style> 
  2.     .list { 
  3.         display: grid; 
  4.         justify-content: space-between
  5.         grid-template-columns: 1fr 1fr 1fr 1fr; /*设置等比列*/ 
  6.         gap: 10px; /*行间距*/ 
  7.     } 
  8.     .item{ 
  9.         background-color: aqua; 
  10.         height: 100px; 
  11.     } 
  12. </style> 
  13.  
  14. <!-- html --> 
  15. <div class="list"
  16.     <div class="item"></div> 
  17.     <div class="item"></div> 
  18.     <div class="item"></div> 
  19.     <div class="item"></div> 
  20.     <div class="item"></div> 
  21.     <div class="item"></div> 
  22. </div> 

效果如下:

上面的三个方案各有各的好处:

  • 方案一的缺点是实现不够优雅,需要增加无用的占位标签。
  • 方案二倒没什么缺点,除了写法会复杂点,但只要封装好mixin在sass中使用足够简单,即使需要兼容ie,也只需要换成float即可。
  • 方案三,兼容性最差,无法在ie中正常使用,但用法最简单,布局甚至比flex还要强大。
  • 综上,实际使用中,还是推荐使用方案二。

    责任编辑:姜华 前端历劫之路
    点赞
    收藏