瀑布圖牆小調研

如題,一道標準的縱向瀑布圖牆<橫向就vice versa啦>,大致分爲三個階段,需求度依次遞增: 階段一:佈局呈現瀑布流。 階段二:每一個item順序應保持一致,先從左至右,再從上至下。 階段三:避免某列過長或太短。也就是多列狀態下,能根據每列長度肯定下一個item應處的列。css

市面上解決方案,也分別對應了不一樣的需求。bash

方案一:column-count ✮

知足:階段一 優勢:利用了css的column-count屬性,方便快捷。 缺點:佈局順序是先從上至下,再從左至右。如圖: 佈局

image

這種效果相似於將全部元素三等分,分別人爲塞到三個container裏的感受。用普通定位亦可以達到。 另,我以爲按MDN的例子,column-count更適用的場景是給文字排版。flex

Ref:HOW TO: Pure CSS masonry layouts ui

方案二:flex + flex-flow: column wrap ✮

知足:階段一 優勢:一樣方便快捷,而且相信對大部分人而言,flex比column-count要更親切些。 缺點:column是縱向排列,因此面臨一樣的順序問題。 不過,加一點小小的訣竅就能夠化腐朽爲神奇☟。flexbox

方案三:flex + flex-flow: column wrap + order ✮✮✮✮

知足:階段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; }
複製代碼

image

因order的權重最高,因此item元素進行了重排。從上而下佈局時,order高的元素都會被推入到以後進行渲染。 一個小問題: code

image

如上圖,原本元素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 渲染結果看起來相似:

image

不過固然,分隔列的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

方案四:grid + 動態grid-row-end ✮✮✮

知足:階段1、階段二 原理:grid佈局的本質是網格塊,那麼不定高度的元素,就能夠以豎跨不定數量的網格塊實現(也就是動態設置grid-row-end)。固然,網格塊的高度越小,細度越大,也越不浪費多出來的網格空間。

image

重點:在頁面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

另外,蘑菇街首頁的僞瀑布圖牆實現,直接將內容分紅幾大豎列來渲染,也是一種不顯得很聰明但實際頗有效的辦法喔,科科。

相關文章
相關標籤/搜索