如題,一道標準的縱向瀑布圖牆<橫向就vice versa啦>,大致分爲三個階段,需求度依次遞增: 階段一:佈局呈現瀑布流。 階段二:每一個item順序應保持一致,先從左至右,再從上至下。 階段三:避免某列過長或太短。也就是多列狀態下,能根據每列長度肯定下一個item應處的列。css
市面上解決方案,也分別對應了不一樣的需求。bash
知足:階段一 優勢:利用了css的column-count屬性,方便快捷。 缺點:佈局順序是先從上至下,再從左至右。如圖: 佈局
這種效果相似於將全部元素三等分,分別人爲塞到三個container裏的感受。用普通定位亦可以達到。 另,我以爲按MDN的例子,column-count更適用的場景是給文字排版。flex
Ref:HOW TO: Pure CSS masonry layouts ui
知足:階段一 優勢:一樣方便快捷,而且相信對大部分人而言,flex比column-count要更親切些。 缺點:column是縱向排列,因此面臨一樣的順序問題。 不過,加一點小小的訣竅就能夠化腐朽爲神奇☟。flexbox
知足:階段1、階段二 原理:使用flex的order屬性將縱向順序打亂成迷惑肉眼的橫向順序。spa
order屬性規定了彈性容器中的可伸縮項目在佈局時的順序。元素按照order屬性的值的增序進行佈局。擁有相同order屬性值的元素按照它們在源代碼中出現的順序進行佈局。3d
關鍵代碼:rest
/*以三豎列爲例*/
.item:nth-child(3n+1) { order: 1; }
.item:nth-child(3n+2) { order: 2; }
.item:nth-child(3n+3) { order: 3; }
複製代碼
因order的權重最高,因此item元素進行了重排。從上而下佈局時,order高的元素都會被推入到以後進行渲染。 一個小問題: code
如上圖,原本元素3應該在第3行的,可是因爲第二列還有不少空位,元素3就順勢插入了第二列結尾。問題就來了,該如何將每列的元素顯性分開,不讓它們順勢填充呢? 那麼每列中間就應該存在一個「分隔列」,它的寬度爲0,高度100%,起隔離做用。
/*使分隔列的高度撐滿整個主軸,也就是高100%*/
flex-basis: 100%;
width: 0;
複製代碼
此時整個渲染隊列應爲:1, 4, 7, 10, <.break>, 2, 5, 8, 11, <.break>, 3, 6, 9, 12 渲染結果看起來相似:
不過固然,分隔列的DOM節點也須要人爲插入了。
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
...
<!--人爲插入的分隔列-->
<span class="item break"></span>
<span class="item break"></span>
<span class="item break"></span>
</div>
複製代碼
總的說來,這個方案我認爲是純css佈局中首屈一指的方案了,不算輕鬆,可是勝在清晰,甚至能夠真的在實際業務中用起來。所以奪得了四顆星!
Ref: CSS masonry with flexbox, :nth-child(), and order
知足:階段1、階段二 原理:grid佈局的本質是網格塊,那麼不定高度的元素,就能夠以豎跨不定數量的網格塊實現(也就是動態設置grid-row-end)。固然,網格塊的高度越小,細度越大,也越不浪費多出來的網格空間。
重點:在頁面onLoad後,取到每一個grid的高度以及每一個item塊裏實際內容的高度,兩相一除,再動態設置item塊應豎跨多少個item. 優勢:思路挺不錯的!創新星給一顆~ 缺點:比較複雜,另外由於須要在頁面剛渲染完成後再操做樣式的變化,因此能夠肉眼看見整個圖牆被撐開的過程。
Ref: Masonry style layout with CSSGrid
知足:階段1、階段2、階段三 感慨:這種方式不可打敗的好處是:絕對不會出錯!想怎麼定位怎麼定位,每次push進新的item時,經過計算已渲染列表的高度,新item想放哪一列就放哪一列。 實際業務場景:
花瓣網: 絕對定位,直接更改top及left,每一個item的高度自動撐開。
/*某個圖牆item*/
position:absolute;
left:504px;
top:6223px;
opacity:1;
複製代碼
pinterest: 絕對定位,經過translate更改座標。不過item高度是已知值,有作懶加載。在窗口resize時,會從新渲染。
/*某個圖牆item*/
top:0px;
left:0px;
transform:translateX(260px) translateY(28459px);
width:260px;
height:695px;
複製代碼
總的來講,若是要我本身選的話~當實現場景偏ui時,好比官網的人物介紹阿這種item有限的瀑布圖,用flex是不錯的選擇;而當實現場景偏業務時,比方無限下拉加載的瀑布圖牆,爲考慮兼容性和更大的可操縱性,我依然會選擇死板卻不會錯的絕對定位 :P
另外,蘑菇街首頁的僞瀑布圖牆實現,直接將內容分紅幾大豎列來渲染,也是一種不顯得很聰明但實際頗有效的辦法喔,科科。