最近写了个页面,想到了用瀑布流实现页面布局。在我看来一个合格的横向瀑布流式布局包含以下几个条件:
-
1、每个内容块高度可以不等,但宽度相等。
由于内容的不确定性,内容块的高度应根据内容高度伸缩。高度相等的话就变成了网格布局,规整倒是规整,不仅没有瀑布效果,内容的个性也无从体现。
-
2、内容块应进行横向排序。
由于是默认的瀑布流式是纵向布局,用户的浏览顺序自上而下。加载的新内容始终排列在最下方,因此整个布局的高度可以无限延展,而宽度始终固定。这就要求内容在有排序需求时,必须从左到右依次填充页面。
-
3、内容块列数固定。
内容块的列数应是可控的,在当前 div 下不会因为容器空间不足造成内容块溢出或缩小。三列的瀑布流,就应该始终是三列。
用 flexbox, :nth-child() 和 order 实现 CSS 瀑布流式布局
用 flexbox 制作瀑布流布局乍看似乎很容易:只要用
flex-flow: column wrap
就能实现。问题在于这个方法实现出的内容块会排序错乱:内容块渲染是由上至下,而用户阅读是由左至右,因此用户看到的内容块顺序可能是1, 3, 6, 2, 4, 7, 8, 5之类的。
在 flexbox 里用
column
布局实现在
row
才能达到的排序绝非易事,但加上
:nth-child()
和
order
这两个属性就能做到不依靠 JavaScript ,仅用CSS实现瀑布流式布局。
先上干货总结:假设要渲染三列布局,用
flex-direction: column
实现 row 排序的话,只需要:
html:
<div class="container">
<div class="item" style="height: 140px"></div>
<div class="item" style="height: 190px"></div>
<div class="item" style="height: 170px"></div>
<div class="item" style="height: 120px"></div>
<div class="item" style="height: 160px"></div>
<div class="item" style="height: 180px"></div>
<div class="item" style="height: 140px"></div>
<div class="item" style="height: 150px"></div>
<div class="item" style="height: 170px"></div>
<div class="item" style="height: 170px"></div>
</div>
css:
/* 让内容按列纵向展示 */
.container {
display: flex;
flex-flow: column wrap;
/* 重新定义内容块排序优先级,让其横向排序 */
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n) { order: 3; }
/* 强制使内容块分列的隐藏列 */
.container::before,
.container::after {
content: "";
flex-basis: 100%;
width: 0;
order: 2;
}
实现效果如下:
缺点:此用法必须要求container,也就是父元素的高度一定,否则就是竖着一排显示
用column属性实现 CSS 瀑布流式布局
.container {
column-count: auto;
column-width: 150px; //单个子元素宽度
}
实现效果如下:
缺点:此用法内容是从上到下展示的