Flexbox
Flexbox布局到今天已經(jīng)是使用非常廣泛的,也算是很成熟的一個(gè)特性。那接下來(lái)我們就看Flexbox怎么實(shí)現(xiàn)瀑布流布局。如果你從未接觸過(guò)Flexbox相關(guān)的屬性,那建議你點(diǎn)擊這里閱讀。如果你覺(jué)得這里信息量過(guò)于太多,那強(qiáng)列建議你閱讀下面幾篇文章,閱讀完之后你對(duì)Flexbox相關(guān)屬性會(huì)有一個(gè)徹底的了解:
- 一個(gè)完整的Flexbox指南
- 圖解CSS3 Flexbox屬性
- 理解Flexbox:你需要知道的一切
- 終極Flexbox屬性查詢(xún)列表
- Flexbox布局實(shí)戰(zhàn)
- 深入理解 flex 布局以及計(jì)算
上面這幾篇文章告訴了你有關(guān)于Flexbox的一切:

接下來(lái)回到我們今天的正題當(dāng)中,使用Flexbox實(shí)現(xiàn)瀑布流布局有兩種方案。
一個(gè)主要的列容器
結(jié)構(gòu)依舊和Multi-columns小節(jié)中展示的一樣。只是在.masonry容器中使用的CSS不一樣:
.masonry {
display: flex;
flex-flow: column wrap;
width: 100%;
height: 800px;
}
之前在.masonry中是通過(guò)column-count來(lái)控制列,這里采用flex-flow來(lái)控制列,并且允許它換行。這里關(guān)鍵是容器的高度,示例中顯式的設(shè)置了height屬性,當(dāng)然除了設(shè)置px值,還可以設(shè)置100vh,讓.masonry容器的高度和瀏覽器視窗高度一樣。記住,這里height可以設(shè)置成任何高度值(采用任何的單位),但不能不顯式的設(shè)置,如果沒(méi)有顯式的設(shè)置,容器就無(wú)法包裹住項(xiàng)目列表。
使用Flexbox布局,對(duì)于.item可以不再使用break-inside:avoid,但其它屬性可以是一樣。同樣的,響應(yīng)式設(shè)置,使用Flexbox實(shí)現(xiàn)響應(yīng)式布局比多列布局要來(lái)得容易,他天生就具備這方面的能力,只不過(guò)我們這里需要對(duì)容器的高度做相關(guān)的處理。前面也提到過(guò)了,如果不給.masonry容器顯式設(shè)置高度是無(wú)法包裹項(xiàng)目列表的,那么這里響應(yīng)式設(shè)計(jì)中就需要在不同的媒體查詢(xún)條件下設(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;
}
}
同樣來(lái)看一個(gè)示例效果:
<iframe id="jmEzEm" src="https://codepen.io/airen/embed/jmEzEm?height=400&theme-id=0&slug-hash=jmEzEm&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è)解決方案有一個(gè)最致命的地方,就是需要顯式的給.masonry設(shè)置height,特別對(duì)于響應(yīng)式設(shè)計(jì)來(lái)說(shuō)這個(gè)更為不友好。而且當(dāng)我們的項(xiàng)目列表是動(dòng)態(tài)生成,而且內(nèi)容不好控制之時(shí),這就更蛋疼了。那么有沒(méi)有更為友好的方案呢?
前面說(shuō)到過(guò)Flexbox有兩種方案,那咱們先來(lái)看方案二,再來(lái)回答這個(gè)問(wèn)題。
單獨(dú)的列容器
這個(gè)方案,我們需要對(duì)我們的HTML結(jié)構(gòu)做一個(gè)變更。變更后的HTML結(jié)構(gòu)看起來(lái)像這樣:
<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,這個(gè)div.column稱(chēng)為列表項(xiàng)目的單獨(dú)容器。在這個(gè)解決方案中,.masonry和.column都通過(guò)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);
}
這里有一個(gè)需要注意,在.column咱們通過(guò)calc()方法來(lái)控制每個(gè)列的寬度,如果你希望是三列,那么可以設(shè)置width: calc(100% / 3);實(shí)際中根據(jù)自己的設(shè)計(jì)來(lái)設(shè)置width:
.masonry {
display: flex;
flex-direction: row;
}
.column {
display: flex;
flex-direction: column;
width: calc(100%/3);
}
這種方案對(duì)應(yīng)的響應(yīng)式設(shè)計(jì),需要在不同的媒體查詢(xún)下修改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);
}
}
效果如下:
<iframe id="PpEPWG" src="https://codepen.io/airen/embed/PpEPWG?height=400&theme-id=0&slug-hash=PpEPWG&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>
從實(shí)戰(zhàn)結(jié)果已經(jīng)告訴你答案了。只不過(guò)在結(jié)構(gòu)上變得冗余一點(diǎn)。
以上摘自大漠w3cplus