你知道黏性元素(Sticky)與瀑布式佈局(Masonry Layout)只用 CSS 就能達到效果嗎?

Peace Pan
萬達寵物系統發展部
5 min readDec 27, 2019

自當年 W3C Recommendation CSS 3 發布後 2011 年 6 月 7 日至今,已經快過 9 年了,雖然 CSS3 目前還尚未制定完成,但許多屬性已經都被有在更新的瀏覽器漸漸支援了。

黏性元素

回到主題,如果你要用 js 實作出一個黏性元素時(元素離開視圖時,依舊黏於畫面上),你可能會需要

  1. 紀錄目標元素的 offset 位置
  2. 監聽父容器的 scroll 位置
  3. 判斷目標元素的 offset 位置是否小於父容器的 scroll 位置
  4. 將目標元素固定

或者改用 IntersectionObserver 來實作

不過隨著瀏覽器支援度,現在幾乎已經可以使用 CSS3 的特性直接達到此需求功能了。

position: sticky 現今支援度 (2019/12)

position: sticky 目前尚未解決的問題只是在 table 元素裡用在 thead 與 tr 時無法正常工作,就是說沒辦法讓 table 裡的欄位固定顯示,其餘元素都是正常支援。

使用方法很簡單,只需要在目標元素掛上以下屬性,不需要任何 js 代碼

position: -webkit-sticky;
position: sticky;
top: 0

就會在元素離開視圖時,自動黏於父容器的 top: 0 上,只有在父容器完全離開視圖時,sticky 元素才會真正離開視圖。簡單的展示可以從以下連結前往觀看。

瀑布式佈局

說到著名的瀑布式佈局,大概就是 pinterest 了,就是每個區塊盡可能的佔滿左右及上下空間而不會有多餘的空間,使用 flexbox 不容易達到這樣子的佈局。用 devtool 查看 pinterest 的網站,可以發現作法大概是

  1. 父容器使用 position: relative
  2. 子元素用 position: absolute 根據內容給予寬與高
  3. 透過 transform 算出區塊在整個父容器裡的 XY 位置

等於需要定義所有要顯示的內容寬與高,一點點的計算錯誤可能就會導致佈局錯亂。

對於簡單的瀑布式佈局,其實可以使用 Grid Layout 就可達成

display: grid 現今支援度 (2019/12)

當把父容器的 display 設成 grid 或 inline-grid 時,所有的子元素都會變成格狀單位,使用 chrome devtool 開啟查看元素時,會呈現特別的 Layout 模式,每個格狀元素會以虛線顯示。

要達成簡單的瀑布式佈局,只需要設定父容器與 Column 的樣式與搭配簡單的 js 代碼即可達成,樣式範例大概如:

.wrapper {
display: grid;
grid-gap: 1em;
grid-template-columns: 1fr 1fr 1fr; /* 一列顯示三行 */
grid-auto-flow: column;
}
.wrapper .column {
display: inherit;
grid-gap: inherit;
grid-auto-rows: min-content;
}

而 js 代碼只需要將原本一維式的資料根據一列要顯示幾行來轉換為二維式的陣列資料即可,如:

[1, 2, 3, 4, 5, 6, 7]
=>
[
[1, 2, 3],
[4, 5, 6],
[7, , ]
]

簡單的展示可以從以下連結前往觀看。

後談

CSS3 剛發佈時,很多新的屬性的功能非常強大,但剛發佈時許多瀏覽器的都尚未支援,而當時剛好是 jQuery 正紅的時候,為了能夠符合尚未支援的瀏覽器,衍生出許多 jQuery 或純 js 的插件,但時至今日,這些在 Github 上的專案很多都已經好幾年都沒有在維護了,隨著技術的發展,這些在當時產生出來的代碼很可能都會被淘汰,除非你還在擁抱 IE。前端技術不斷發展,只能要求自己經常性的吸收新知識。

--

--