CSS 的 position 值中,有一個非常有用的值 -- position: sticky
,通常會被用於各種吸頂,吸底,吸邊的效果中。
如果你對 sticky
還不太熟悉,可以先看看我的這篇文章:使用 position:sticky 實現粘性佈局,當然,這篇文章裡面有稍微探討 position: sticky
生效或者說失效的規則,但是不太充分。
最近遇到一些 position-sticky
失效的場景,所以總結了一下。
position-sticky 生效的原理
在 W3 官方文件中的定義是:Sticky positioning is similar to relative positioning except the offsets are automatically calculated in reference to the nearest scrollport.
轉換成通俗的大白話就是,Sticky 定位類似於相對定位,(當它表現為 fixed 定位的特性時)會根據最近的滾動容器(nearest scrollport)自動計算偏移量。
其中有一個非常重要的概念就是 nearest scrollport,它表示 sticky 元素在即將消失前會相對它最近的 scrollport 去做定位。
正常的 DEMO
所以正常而言,類似下面的這種情況,sticky 是可以正常展示的。
<div class="container"> - 可滾動的容器 scrollport <div class="sticky"> - 設定了 sticky 的元素
CodePen Demo -- Normal Sticky Demo
失效的 position: sticky
1、包裹的父容器高度與 sticky 元素一致
有趣的是,如果在 .sticky
元素和你希望 .sticky
生效吸附的滾動元素中間,新增上一層 .parent
的 div 元素,不給 div 新增任何樣式,sticky 則失效了。
譬如是這樣:
<div class="container"> - 可滾動的容器 scrollport <div class="parent"> <div class="sticky"> - 設定了 sticky 的元素
CodePen Demo -- invalid Sticky Demo 1
失效原因:此時 .sticky
元素的最近的 scrollport 變成了它的父容器 div,而父容器 div 的高度和 .sticky
元素的高度是一樣的,所以表現不出 fixed 的特性。
其實,這裡不算失效,我們只需要將包裹 .sticky
元素的父容器的高度設定的大於 .sticky
元素本身,也能看到效果。
譬如,我們可以加上
.parent { height: 100vh; }
此時,sticky
將重新生效,像是這樣:
其實,造成這種現象的本質原因是,設定了 position: sticky
的元素吸附的基準元素從 .container
變成了 .parent
。
2、包裹的父容器設定了 overflow: hidden
第二種情況,也會導致 position: sticky
的 fixed 定位特性失效。也就是 .sticky
元素的祖先容器存在 overflow: hidden。類似這樣
<div class="container"> - 可滾動的容器 scrollport <div class="hidden"> - 設定了 overflow: hidden <div class="sticky"> - 設定了 sticky 的元素
CodePen Demo -- invalid Sticky Demo 2
在上面這個 DEMO 裡面,設定了 sticky
的元素的父元素 hidden
元素,它的高度是遠比 stikcy
元素高的,但是滾動的過程中卻沒有表現出 fixed 的特性。
原因在於,設定了 overflow: hidden
的元素,它不再代用滾動的特性,當
sticky元素吸附於
.hidden元素的頂部時,它隨著
.hidden` 元素本身在 container 移動。所以,所有的 sticky 元素都會被滾動出 container 的滾動區域。
當然,這裡有一點比較奇怪的是,.sticky
元素相對 .hidden
元素進行 fixed 定位,而不是相對 .container
元素進行 fixed 定位,表面設定了 overflow: hidden
的元素,它也是一個 scrollport。
其實,不止是 overflow: hidden
,設定為 position: sticky
元素的任意父節點的 overflow 屬性必須是 visible,否則 position:sticky
不會生效。
總結一下
看完上面幾個 DEMO,可以好好總結一下 position:sticky
的生效規則,明白了生效規則就會知道為什麼有的時候設定的 sticky
會失效:
- 須指定 top, right, bottom 或 left 四個閾值其中之一(且達到設定的閾值),才可使粘性定位生效。否則其行為與相對定位相同;
- 並且 top 和 bottom 同時設定時,top 生效的優先順序高,left 和 right 同時設定時,left 的優先順序高
- 設定為
position: sticky
的元素的任意父節點的 overflow 屬性必須是 visible,否則position:sticky
不會生效;在滿足上述情況下,設定了position: sticky
的元素的父容器的高度必須大於當前元素,否則也會失效。(當然,此時,sticky
吸附的基準元素就會變成父元素)- 如果 position: sticky 元素的任意父節點定位設定為 position: overflow,則父容器無法進行滾動,所以 position:sticky 元素也不會有滾動然後固定的情況
- 在滿足上述情況下,設定了
position: sticky
的元素的父容器的高度必須大於當前元素,否則也會失效。(當然,此時,sticky
吸附的基準元素就會變成父元素)
最後
好了,本文到此結束。
更多精彩 CSS 技術文章彙總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏。
如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。