瀑布流布局
许多网站采用瀑布流布局的形式对 items 进行排版,看上去很有美感。它看上去像是不规则的网格布局。
瀑布流布局的特点如下:
- 每列元素宽度固定,高度不定。
- 下面的元素会仅接着上面的元素放置,不会留下缝隙。
简单实现
我们可以使用简单的 CSS 实现瀑布流布局:
:::: tabs ::: tab HTML
<article>
<section>
<p>1.Lorem ipsum dolor sit amet, consectetur.</p>
</section>
<section>
<p>
2.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Error aliquid reprehenderit expedita odio beatae est.
</p>
</section>
<section>
<p>3.Lorem ipsum dolor sit amet, consectetur.</p>
</section>
<section>
<p>4.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nobis quaerat suscipit ad.</p>
</section>
<section>
<p>
5.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem nihil alias amet dolores fuga totam sequi a
cupiditate ipsa voluptas id facilis nobis.
</p>
</section>
<section>
<p>
6.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rem ut debitis dolorum earum expedita eveniet
voluptatem quibusdam facere eos numquam commodi ad iusto laboriosam rerum aliquam.
</p>
</section>
<section>
<p>7.Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
</section>
<section>
<p>
8.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat architecto quis tenetur fugiat veniam iste
molestiae fuga labore!
</p>
</section>
<section>
<p>
9.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Odit accusamus tempore at porro officia rerum est
impedit ea ipsa tenetur. Labore libero hic error sunt laborum expedita.
</p>
</section>
<section>
<p>10.Lorem ipsum dolor sit.</p>
</section>
<section>
<p>
11.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima asperiores eveniet vero velit eligendi aliquid
in.
</p>
</section>
<section>
<p>12.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloribus dolorem maxime minima animi cum.</p>
</section>
</article>
::: ::: tab CSS
article {
column-width: 200px;
column-gap: 15px;
}
section {
box-sizing: border-box;
display: inline-block;
margin-top: 15px;
padding: 15px;
width: 100%;
border: 1px solid black;
}
::: ::: tab 效果 ::: ::::
就如上面的 CSS 所展示的那样,使用 column-width
和 column-gap
配合 inline-block
元素就可以生成瀑布流布局。
Notice
column-width
控制列宽,容器将容纳尽可能多的列数但不会让任何一个元素宽度小于列宽。
column-gap
控制每列的间隙。
在 FireFox 上,你可以使用 grid
创造瀑布流:
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry;
}
grid-template-rows: masonry
是个不错的设想,但截至文章发布之前,该特性并不被除 FireFox 之外的其他浏览器支持。
我们再来看看上面代码实现的效果:
可以发现元素的顺序并没有按照从左到右横向排列,而是按照纵向排列的,也就是说第二个元素排在了第一个元素的下面而不是右边。如何解决这个问题呢?
我们需要使用 nth-child
重新排列元素。
使用 nth-child
重新排列元素
假设我们需要渲染一个三列的瀑布流,那么第一列元素的应该是序号为 1,4,7,9...的元素,他们都满足一个条件,就是序号为 3*(行数-1)+1
。同理,第二行为 3*(行数-1)+2
,第三行为 3*(行数-1)+3
。
section:nth-child(3n + 1) {
order: 1;
}
section:nth-child(3n + 2) {
order: 2;
}
section:nth-child(3n + 3) {
order: 3;
}
Notice
order
属性用于在 flex
或 grid
中对元素进行排序。
然后我们将容器设置成 flex
布局,设置为纵向排列并且可换列:
article {
display: flex;
flex-flow: column wrap;
align-content: space-between;
height: 600px;
column-gap: 7.5px;
}
子元素设置一下宽度和间距:
section {
width: calc(100% / 3);
margin-bottom: 15px;
border: 1px solid black;
}
效果如下:
似乎效果不是预想的那样,由于我们设置容器高度为 600px
的原因,当第一行有充足的空间时,第二行和第三行的元素也合并到前一行来占位置了。
我们可以通过伪元素来分割这三列解决这个问题。
article::before,
article::after {
content: '';
flex-basis: 100%;
width: 0;
order: 2;
}
我们将伪元素的 order
设置为 2,那么 ::before
会分割第一和第二行,而 ::after
会分割第二和第三行,我们将这两个伪元素高亮出来看一下:
这样我们就用纯 CSS 实现了一个正常顺序的瀑布流了。
我们可以看出这个方法有一些明显的缺点:
- 容器必须明确设置足够大的高度,如果渲染无限刷新列表的话,该方法会失效。
- 列数不能动态改变。
- 两个伪元素分割的策略在三列以上的瀑布流中不适用。
总结
基于以上的讨论,如果我们及想要响应式渲染,还想要正确的显示顺序,那还是自己找个第三方库来实现吧 😂。