【後知後覺系列】css position: sticky 屬性以及某些場景的使用

首發於個人 Blogcss

不知什麼時候,曾經咱們認爲的東西便會被打破,若是咱們不堅持着去學習,那麼咱們終將會被社會所淘汰。因而我決定寫《後知後覺系列》來記錄一下我曾經跟不上的知識和關鍵點,內容不必定複雜,內容含量不必定高,也許別人已經寫過一個同樣的教程了,可是但願你能從個人筆記中獲取你認爲重要的東西,在紛繁複雜的工做中留下一個真正極客的世界,但願某一天這些東西都可以運用到工做當中。——XGHeavenhtml

記得先看一下目錄,找到你喜歡好奇的內容去針對性閱讀,畢竟我不是來寫教程的。git

position: sticky 這到底是一個什麼鬼?

最近公司在用 Regular 封裝一個表格組件,須要實現固定表頭的功能。這個是幾乎全部的組件庫都會實現的一個效果,因此實現方式有不少種:github

  1. 由於 thead/tr 的 position 屬性是無效的,因此須要單獨用 div 建立一個表頭。而後設置這個表頭的 position: absolute,同時 top: 0。同時這種模式下,須要用戶指定每一列的寬度,保證自制的表頭和下面原生的表格一一對應起來。若是不指定的話,也能夠等待 dom 渲染完成以後,再測量寬度。好比 Ant Design 就是使用的這種方式。
  2. 由於上面那種方案的難點在於沒法很好的保證自制表頭和原生表格寬度的一致性,因此咱們組的大佬提出了使用原生 thead,監聽 scroll 事件,設置 transform 屬性使得表頭進行偏移,從而實現 fixHeader 的問題,這種方式解決了第一個的問題,可是須要手動監聽 scroll 事件,在快速滾動的狀況下,可能會有必定的性能問題。並且不夠優雅。若是後面的表格內容中有 position: relative 的元素,會覆蓋到表頭。

不論是哪一種方式,我總感受不是很完美,因而我就在思考,除了手動更新的方式,難道就沒有一些比較好的方式去作。而後我就去翻看了 github 的固定表頭的方式,頓時豁然開朗。因而就延伸出了這篇文章,position: sticky 屬性。api

Pay Attention:後面所講的內容就不怎麼和表格固定表頭相關,若是你對錶格固定表頭或者固定列有必定問題,能夠查看網易考拉的這篇文章 《一塊兒來聊聊table組件的固定列》瀏覽器

當第一眼看到這個熟悉的時候,第一句話就是「我 CA」,這 TMD 是什麼鬼屬性,position 何時有了這個屬性。因而去看了 MDN 的介紹,能夠理解爲,這個屬性是實現固定頂部最簡單的實現方式dom

他實際上是一種 position:relativeposition: fixed 的結合體,必定要配合 top/right/bottom/left 的屬性一塊兒纔有做用,設置對應方向的最小值。當大於最小值的時候,他就像 relative 同樣,做爲文檔流的一部分,而且 top/right/bottom/left 屬性也會失效。不然當小於設置的值的時候表現的像 fixed,只不過這個 fixed 再也不現對於窗口,而是相對於最近的可滾動塊級元素。ide

若是你看過其餘關於 sticky 的文章,大部分都會以黏貼的意思來解釋他,那麼很明顯,確實也是這個意思,若是你以爲看了其餘教程可以清楚的話,那麼能夠不用看我這篇了,若是你沒看懂的話,能夠來我這裏看看。性能

廢話少說,咱們先來看一下如何正確使用 sticky。學習

正確的使用姿式

如下的代碼預覽請使用最新 Chrome 查看,或者支持 position: sticky 的瀏覽器查看。部分網站不支持 iframe,能夠去個人 Blog 查看

  1. position: sticky 只相對於第一個有滾動的父級塊元素(scrolling mechanism,經過 overflow 設置爲 overflow/scroll/auto/overlay 的元素),而不是父級塊元素。

    See the Pen position sticky 相對於最外面的可滾動父級 by Bradley Xu (@xgheaven) on CodePen.
  2. position: sticky 只有當設置對應的方向(top/right/bottom/left),纔會有做用,而且能夠互相疊加,能夠同時設置四個方向。

  3. 即便設置了 position: sticky,也只能顯示在父級塊元素的內容區域,他沒法超出這個區域,除非你設置了負數的值。

  4. position: sticky 並不會觸發 BFC,簡單來說就是計算高度的時候不會計算 float 元素。

  5. 當設置了 position: sticky 以後,內部的定位會相對於這個元素

    See the Pen position sticky 內部絕對定位相對於這個元素 by Bradley Xu (@xgheaven) on CodePen.
  6. 雖然 position: sticky 表現的像 relative 或者 fixed,因此也是能夠經過 z-index 設置他們的層級。當這個元素的後面的兄弟節點會覆蓋這個元素的時候,能夠經過 z-index 調節層級。

    See the Pen position: sticky 經過 z-index 調節層級 by Bradley Xu (@xgheaven) on CodePen.

當你懂了這幾個以後,其實這個屬性就用起來就很簡單了。

舉個栗子 - 通信錄列表頭部

no code no bb,直接上代碼。

See the Pen position sticky 通信錄 Demo by Bradley Xu ( @xgheaven) on CodePen.

拓展思考

如何檢測是否已經被固定?

最多見的需求就是,當還在文檔流當中的時候,正常顯示,可是當固定住的時候,添加一些陰影或者修改高度等操做。要想實現這個效果,第一反應可能就是手動監聽 scroll 事件,判斷位置,這固然是沒有問題的,可是隨之而來的確實性能的損耗。

最好的方式是使用 IntersectionObserver,這是一個能夠監聽一個元素是否顯示在視窗以內的 API,具體內容見阮老師的《IntersectionObserver API 使用教程》。基本原理就是在一段滾動的頭部和尾部分別添加兩個崗哨,而後經過判斷這兩個崗哨的出現和消失的時機,來判斷元素是否已經被固定。

例子詳見此處

那能不能實現表格頭/列固定呢?

理想很豐滿,顯示很骨感,由於 thead/tbody 對 position 無愛,因此也就不支持 sticky 屬性,因此咱們仍是要單首創建一個頭部。

後來通過網友提醒,本身又去研究了一下,發現仍是有辦法作到固定表頭和列的。

首先針對 Firefox,它自己就支持 thead/tbody 的 position 屬性,因此能夠直接經過對 thead/tbody 設置 position 來實現。而對於 Chrome 瀏覽器來說,能夠經過設置 thead 內的 th 來實現。具體見 Demo.

See the Pen position sticky 經過設置 td 來實現固定表頭 by Bradley Xu (@xgheaven) on CodePen.

而後好像就沒有了,謝謝觀看水水的《後知後覺系列》

相關文章
相關標籤/搜索