瀑布流布局其核心是基于一個(gè)網(wǎng)格的布局,而且每行包含的項(xiàng)目列表高度是隨機(jī)的(隨著自己內(nèi)容動(dòng)態(tài)變化高度),同時(shí)每個(gè)項(xiàng)目列表呈堆棧形式排列,最為關(guān)鍵的是,堆棧之間彼此之間沒(méi)有多余的間距差存大。還是上張圖來(lái)看看我們說(shuō)的瀑布流布局是什么樣子。

當(dāng)初要實(shí)現(xiàn)這樣的布局都是依賴于JavaScript來(lái)實(shí)現(xiàn),所以當(dāng)時(shí)出現(xiàn)過(guò)很多實(shí)現(xiàn)瀑布流布局的插件。比如Masonry、Isotope等都是非常有名的插件。但使用純CSS來(lái)實(shí)現(xiàn),當(dāng)時(shí)還是非常困難的,不管是使用float還是inline-block布局都無(wú)法很好的控制列表項(xiàng)目堆棧之間的間距。最終得到的效果就像下面這樣:

現(xiàn)在距離2012年已經(jīng)過(guò)去了五個(gè)年頭,CSS的技術(shù)更新也是日新月異,在這幾年當(dāng)中出現(xiàn)了很多新的布局方法,比如多列布局multi-columns、Flexbox布局以及今年瀏覽器支持有Grid布局。既然CSS的布局有這么多的變化,那么今天有沒(méi)有不借助任何JavaScript(純CSS方案)能否實(shí)現(xiàn)瀑布流布局?答案是肯定的,接下來(lái)的內(nèi)容,我們就使用不同的CSS布局方案來(lái)實(shí)現(xiàn)瀑布流布局。
Multi-columns
首先最早嘗試使用純CSS方法解決瀑布流布局的是CSS3 的Multi-columns。其最早只是用來(lái)用來(lái)實(shí)現(xiàn)文本多列排列(類似報(bào)紙雜志樣的文本排列)。但對(duì)于前端同學(xué)來(lái)說(shuō),他們都是非常具有創(chuàng)意和創(chuàng)新的,有人嘗試通過(guò)Multi-columns相關(guān)的屬性column-count、column-gap配合break-inside來(lái)實(shí)現(xiàn)瀑布流布局。
比如我們有一個(gè)類似這樣的HTML結(jié)構(gòu):
<div class="masonry">
<div class="item">
<div class="item__content">
</div>
</div>
<div class="item">
<div class="item__content">
</div>
</div>
<!-- more items -->
</div>
其中div.masonry是瀑布流的容器,其里面放置了n個(gè)列表div.item。為了節(jié)約篇幅,上面代碼僅列了兩個(gè)。結(jié)構(gòu)有了,現(xiàn)在來(lái)看CSS。在.masonry中設(shè)置column-count和column-gap,前者用來(lái)設(shè)置列數(shù),后者設(shè)置列間距:
.masonry {
column-count: 5;
column-gap: 0;
}
上面控制了列與列之間的效果,但這并不是最關(guān)鍵之處。當(dāng)初純CSS實(shí)現(xiàn)瀑布流布局中最關(guān)鍵的是堆棧之間的間距,而并非列與列之間的控制(說(shuō)句實(shí)話,列與列之間的控制float之類的就能很好的實(shí)現(xiàn))。找到實(shí)現(xiàn)痛楚,那就好辦了?;蛟S你會(huì)問(wèn)有什么CSS方法可以解決這個(gè)。在CSS中有一個(gè)break-inside屬性,這個(gè)屬性也是實(shí)現(xiàn)瀑布流布局最關(guān)鍵的屬性。
.item {
break-inside: avoid;
box-sizing: border-box;
padding: 10px;
}
其中break-inside:avoid為了控制文本塊分解成單獨(dú)的列,以免項(xiàng)目列表的內(nèi)容跨列,破壞整體的布局。當(dāng)然為了布局具有響應(yīng)式效果,可以借助媒體查詢屬性,在不同的條件下使用column-count設(shè)置不同的列,比如:
.masonry {
column-count: 1; // one column on mobile
}
@media (min-width: 400px) {
.masonry {
column-count: 2; // two columns on larger phones
}
}
@media (min-width: 1200px) {
.masonry {
column-count: 3; // three columns on...you get it
}
}
<!-- etc. -->
比如下面的這個(gè)示例:
<iframe id="ybyvEM" src="https://codepen.io/airen/embed/ybyvEM?height=400&theme-id=0&slug-hash=ybyvEM&default-tab=result&user=airen" scrolling="no" frameborder="0" height="400" allowtransparency="true" allowfullscreen="true" class="cp_embed_iframe undefined" style="box-sizing: inherit; width: 940px; overflow: hidden;"></iframe>
看到上面示例的效果,這個(gè)時(shí)候是不是有點(diǎn)成就感了,是不是覺(jué)得CSS更神奇了?