瀑布流布局有一個專業(yè)的英文名稱Masonry Layouts。瀑布流布局已經(jīng)有好多年的歷史了政勃,我最早知道這個名詞的時候大約是在2012年唧龄,當(dāng)時Pinterest網(wǎng)站的布局就是使用的這種流式布局,簡言之像Pinterest網(wǎng)站這樣的布局就稱之為瀑布流布局奸远,也有人稱之為Pinterest 布局既棺。
瀑布流布局其核心是基于一個網(wǎng)格的布局,而且每行包含的項目列表高度是隨機的(隨著自己內(nèi)容動態(tài)變化高度)懒叛,同時每個項目列表呈堆棧形式排列丸冕,最為關(guān)鍵的是,堆棧之間彼此之間沒有多余的間距差存大薛窥。還是上張圖來看看我們說的瀑布流布局是什么樣子胖烛。
當(dāng)初要實現(xiàn)這樣的布局都是依賴于JavaScript來實現(xiàn),所以當(dāng)時出現(xiàn)過很多實現(xiàn)瀑布流布局的插件诅迷。比如Masonry佩番、Isotope等都是非常有名的插件。但使用純CSS來實現(xiàn)罢杉,當(dāng)時還是非常困難的趟畏,不管是使用float
還是inline-block
布局都無法很好的控制列表項目堆棧之間的間距。最終得到的效果就像下面這樣:
現(xiàn)在距離2012年已經(jīng)過去了五個年頭屑那,CSS的技術(shù)更新也是日新月異拱镐,在這幾年當(dāng)中出現(xiàn)了很多新的布局方法,比如多列布局multi-columns
持际、Flexbox布局以及今年瀏覽器支持有Grid布局沃琅。早前在《CSS布局的未來》一文中有對這些布局做過闡述。既然CSS的布局有這么多的變化蜘欲,那么今天有沒有不借助任何JavaScript(純CSS方案)能否實現(xiàn)瀑布流布局益眉?答案是肯定的,接下來的內(nèi)容姥份,我們就使用不同的CSS布局方案來實現(xiàn)瀑布流布局郭脂。
Multi-columns
首先最早嘗試使用純CSS方法解決瀑布流布局的是CSS3 的Multi-columns。其最早只是用來用來實現(xiàn)文本多列排列(類似報紙雜志樣的文本排列)澈歉。但對于前端同學(xué)來說展鸡,他們都是非常具有創(chuàng)意和創(chuàng)新的,有人嘗試通過Multi-columns相關(guān)的屬性column-count
埃难、column-gap
配合break-inside
來實現(xiàn)瀑布流布局
比如我們有一個類似這樣的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
個列表div.item
涤久。為了節(jié)約篇幅,上面代碼僅列了兩個忍弛。結(jié)構(gòu)有了响迂,現(xiàn)在來看CSS。在.masonry
中設(shè)置column-count
和column-gap
细疚,前者用來設(shè)置列數(shù)蔗彤,后者設(shè)置列間距:
.masonry { column-count: 5; column-gap: 0; }
上面控制了列與列之間的效果,但這并不是最關(guān)鍵之處疯兼。當(dāng)初純CSS實現(xiàn)瀑布流布局中最關(guān)鍵的是堆棧之間的間距然遏,而并非列與列之間的控制(說句實話,列與列之間的控制float
之類的就能很好的實現(xiàn))吧彪。找到實現(xiàn)痛楚啦鸣,那就好辦了±囱酰或許你會問有什么CSS方法可以解決這個。在CSS中有一個break-inside
屬性香拉,這個屬性也是實現(xiàn)瀑布流布局最關(guān)鍵的屬性啦扬。
.item { break-inside: avoid; box-sizing: border-box; padding: 10px; }
其中break-inside:avoid
為了控制文本塊分解成單獨的列,以免項目列表的內(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. -->
比如下面的這個示例:點擊預(yù)覽
看到上面示例的效果,這個時候是不是有點成就感了苦掘,是不是覺得CSS更神奇了换帜?
Flexbox
Flexbox布局到今天已經(jīng)是使用非常廣泛的,也算是很成熟的一個特性鹤啡。那接下來我們就看Flexbox怎么實現(xiàn)瀑布流布局惯驼。如果你從未接觸過Flexbox相關(guān)的屬性,那建議你點擊這里閱讀递瑰。如果你覺得這里信息量過于太多祟牲,那強列建議你閱讀下面幾篇文章,閱讀完之后你對Flexbox相關(guān)屬性會有一個徹底的了解:
- 一個完整的Flexbox指南
- 圖解CSS3 Flexbox屬性
- 理解Flexbox:你需要知道的一切
- 終極Flexbox屬性查詢列表
- Flexbox布局實戰(zhàn)
-
深入理解 flex 布局以及計算
上面這幾篇文章告訴了你有關(guān)于Flexbox的一切:
接下來回到我們今天的正題當(dāng)中抖部,使用Flexbox實現(xiàn)瀑布流布局有兩種方案说贝。
一個主要的列容器
結(jié)構(gòu)依舊和Multi-columns小節(jié)中展示的一樣。只是在.masonry
容器中使用的CSS不一樣:
.masonry {
display: flex;
flex-flow: column wrap;
width: 100%;
height: 800px;
}
之前在.masonry
中是通過column-count
來控制列慎颗,這里采用flex-flow
來控制列乡恕,并且允許它換行言询。這里關(guān)鍵是容器的高度,示例中顯式的設(shè)置了height
屬性几颜,當(dāng)然除了設(shè)置px
值倍试,還可以設(shè)置100vh
,讓.masonry
容器的高度和瀏覽器視窗高度一樣蛋哭。記住县习,這里height
可以設(shè)置成任何高度值(采用任何的單位),但不能不顯式的設(shè)置谆趾,如果沒有顯式的設(shè)置躁愿,容器就無法包裹住項目列表。
使用Flexbox布局沪蓬,對于.item
可以不再使用break-inside:avoid
彤钟,但其它屬性可以是一樣。同樣的跷叉,響應(yīng)式設(shè)置逸雹,使用Flexbox實現(xiàn)響應(yīng)式布局比多列布局要來得容易,他天生就具備這方面的能力云挟,只不過我們這里需要對容器的高度做相關(guān)的處理梆砸。前面也提到過了,如果不給.masonry
容器顯式設(shè)置高度是無法包裹項目列表的园欣,那么這里響應(yīng)式設(shè)計中就需要在不同的媒體查詢條件下設(shè)置不同的高度值:
.masonry {
height: auto;
}
@media screen and (min-width: 400px) {
.masonry {
height: 1600px;
}
}
@media screen and (min-width: 600px) {
.masonry {
height: 1300px;
}
}
@media screen and (min-width: 800px) {
.masonry {
height: 1100px;
}
}
@media screen and (min-width: 1100px) {
.masonry {
height: 800px;
}
}
同樣來看一個示例效果:點擊預(yù)覽
這個解決方案有一個最致命的地方帖世,就是需要顯式的給.masonry
設(shè)置height
,特別對于響應(yīng)式設(shè)計來說這個更為不友好沸枯。而且當(dāng)我們的項目列表是動態(tài)生成日矫,而且內(nèi)容不好控制之時,這就更蛋疼了绑榴。那么有沒有更為友好的方案呢哪轿?
前面說到過Flexbox有兩種方案,那咱們先來看方案二翔怎,再來回答這個問題缔逛。
單獨的列容器
這個方案,我們需要對我們的HTML結(jié)構(gòu)做一個變更姓惑。變更后的HTML結(jié)構(gòu)看起來像這樣:
<div class="masonry">
<div class="column">
<div class="item">
<div class="item__content">
</div>
</div>
<!-- more items -->
</div>
<div class="column">
<div class="item">
<div class="item__content">
</div>
</div>
<!-- more items -->
</div>
<div class="column">
<div class="item">
<div class="item__content">
</div>
</div>
<!-- more items -->
</div>
</div>
不難發(fā)現(xiàn)褐奴,在div.item
外面包了一層div.column
,這個div.column
稱為列表項目的單獨容器于毙。在這個解決方案中敦冬,.masonry
和.column
都通過display:flex
屬性將其設(shè)置為Flex容器,不同的是.masonry
設(shè)置為行(flex-direction:row
)唯沮,而.column
設(shè)置為列(flex-direction
):
.masonry {
display: flex;
flex-direction: row;
}
.column {
display: flex;
flex-direction: column;
width: calc(100%/3);
}
這里有一個需要注意脖旱,在.column
咱們通過calc()
方法來控制每個列的寬度堪遂,如果你希望是三列,那么可以設(shè)置width: calc(100% / 3)
;實際中根據(jù)自己的設(shè)計來設(shè)置width
:
.masonry {
display: flex;
flex-direction: row;
}
.column {
display: flex;
flex-direction: column;
width: calc(100%/3);
}
這種方案對應(yīng)的響應(yīng)式設(shè)計萌庆,需要在不同的媒體查詢下修改width
值溶褪,比如:
.masonry {
display: flex;
flex-direction: column;
}
@media only screen and (min-width: 500px) {
.masonry {
flex-direction: row;
}
}
.column {
display: flex;
flex-flow: column wrap;
width: 100%;
}
@media only screen and (min-width: 500px) {
.column {
width: calc(100%/5);
}
}
效果如下:點擊預(yù)覽
從實戰(zhàn)結(jié)果已經(jīng)告訴你答案了。只不過在結(jié)構(gòu)上變得冗余一點践险。
Grid
Grid將是布局當(dāng)中的一把利劍猿妈,也可以說是神器,特別是今年得到了眾多瀏覽器的支持巍虫。記得去年在CSSConf分享后彭则,有同學(xué)問我Grid是否能實現(xiàn)瀑布流的布局。說實話占遥,雖然Grid對于布局而言是非常的強大俯抖,但要很好的實現(xiàn)瀑布流布局還是非常的蛋疼。@Rachel Andrew在她分享的文章中也特意提到過實現(xiàn)瀑布流的方案瓦胎。從文章中摘出有關(guān)于瀑布流布局的那部分內(nèi)容芬萍。
Grid制作瀑布流,對于結(jié)構(gòu)而言和Multi-columns示例中的一樣搔啊。只不過在.masonry
使用display:grid
來進行聲明:
.masonry {
display: grid;
grid-gap: 40px;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(50px, auto);
}
對于.item
較為蛋疼担忧,需要分別通過grid-row
和grid-column
來指定列表項目所在的區(qū)域,比如:
.masonry > div:nth-child(1) {
grid-row: 1 / 4;
grid-column: 1;
}
.masonry > div:nth-child(2) {
grid-row: 1 / 3;
grid-column: 2;
}
...
將效果Fork過來:點擊預(yù)覽
在Grid中有自動排列的算法的屬性:
- 如果沒有明確指定網(wǎng)格項目位置坯癣,網(wǎng)格會按自動排列算法,將它最大化利用可用空間
- 如果在當(dāng)前行沒有可用位置最欠,網(wǎng)格會自動搜索下一行示罗,這樣會造成一定的差距,浪費可用空間
- 可以把
grid-auto-flow
的row
值改變auto
芝硬,可以切換搜索順序 -
grid-auto-flow
還可以接受另一個關(guān)鍵詞蚜点。默認(rèn)情況下,其值是sparse
拌阴,但我們可以將其顯式的設(shè)置為dense
绍绘,讓網(wǎng)格項目試圖自動填補所有可用的空白空間
言外之意,Grid中自動排列的算法對于實現(xiàn)瀑布流布局有很大的幫助迟赃。不過對于堆棧(列表項目)高度不能友好的控制陪拘。
總結(jié)
這篇文章主要介紹了如何使用純CSS實現(xiàn)瀑布流的布局。文章簡單介紹了三種實現(xiàn)方案:Multi-columns纤壁、Flexbox和Grid左刽。從上面的示例或者實現(xiàn)手段而言,較我友好的是Flexbox的方案酌媒。當(dāng)然欠痴,隨著CSS Grid特性的完善迄靠,使用Grid實現(xiàn)瀑布流布局將會變得更為簡單和友好。那讓我們拭目以待喇辽。當(dāng)然如果你覺得這些方案都不太好掌挚,你可以依舊可以考慮JavaScript的解決方案。如果你有更好的解決方案菩咨,也希望能在下面的評論中與我們一起分享吠式。
著作權(quán)歸作者所有。
商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處旦委。
原文: https://www.w3cplus.com/css/pure-css-create-masonry-layout.html ? w3cplus.com