首頁 >web前端 >js教程 >CSS'位置:粘性” - 介紹和polyfills

CSS'位置:粘性” - 介紹和polyfills

Lisa Kudrow
Lisa Kudrow原創
2025-02-21 08:52:09836瀏覽

CSS

關鍵要點

  • CSS 的 position: sticky 屬性允許導航欄或其他元素在用戶滾動時保持可見,而無需固定在頁面上。此屬性在其父元素內表現得像靜態定位,直到達到給定的偏移閾值,此時它就像值被設置為 fixed 一樣。
  • 傳統上實現此效果的方法涉及 JavaScript,其中監聽頁面的滾動事件,並使用 JavaScript 根據視口的當前位置更改 positiontop 屬性的值。但是,當元素的位置更改為 fixed 時,此方法可能會導致問題,從而導致它離開頁面流,並且下方的元素“向上跳躍”。
  • 目前,“position: sticky”屬性的瀏覽器支持有限。但是,有一些 polyfill 可用於提供此功能,包括 Filament Group 的 fixed-sticky、Matthew Phillips 的 position–sticky- 和 Oleg Korsunsky 的 Stickyfill。

如果您閱讀過 Annarita Tranfici 的文章《Obvious Design always wins》,您可能會同意她的說法:

人們期望看到常見的模式:在頁面頂部找到主菜單,在右上角找到搜索框,在底部找到頁腳,等等。

我同意人們期望網站的某些組件放置在特定位置,在我看來,對於主菜單來說,這一點更為重要。

有時,由於客戶的要求或因為我們已經確定這是最佳方法,我們可能需要主導航始終在頁面上可見,而無需將其固定到位,基本上跟隨頁面內容。近年來,許多基於 JavaScript 的解決方案問世,因為僅 CSS 無法完成此任務。

在本文中,我們將討論 position: sticky,這是解決此問題的新的 CSS 解決方案。

我們解決什麼問題?

在討論此 position 屬性的新值之前,讓我們更好地理解我們試圖解決的問題。

假設我們精彩網站的主菜單位於標題之後,但仍在頁面頂部(不在側邊欄中),並且佔據所有可用寬度。這可能看起來像這樣:

CodePen 示例鏈接

我們想要實現的是,當用戶滾動頁面時,一旦菜單位於視口頂部,菜單就不會滾動到視圖之外,而是會粘在頂部位置——就像它應用了position: fixed一樣(僅當它到達視口頂部時)。

要使用傳統代碼實現此目的,我們需要添加一些 JavaScript。我們監聽頁面的滾動事件,並使用 JavaScript 根據視口的當前位置更改 positiontop 屬性的值。具體來說,當菜單位於視口頂部時,我們需要向菜單添加 top: 0position: fixed,否則將屬性恢復為其默認值。

另一種類似的方法是在我們的 CSS 中創建一個包含這些值的類,然後根據需要使用 JavaScript 添加和刪除該類,這可能看起來像這樣:

<code class="language-javascript">var menu = document.querySelector('.menu')
var menuPosition = menu.getBoundingClientRect().top;
window.addEventListener('scroll', function() {
    if (window.pageYOffset >= menuPosition) {
        menu.style.position = 'fixed';
        menu.style.top = '0px';
    } else {
        menu.style.position = 'static';
        menu.style.top = '';
    }
});</code>

請注意,此代碼段不處理舊版本的 Internet Explorer。如果您需要處理這些瀏覽器(可憐的您!),我將提供一些您可以考慮的 polyfill 選項。

此第二步的實時演示如下所示:

CodePen 示例鏈接

但是等等!你能發現這段代碼引起的問題嗎?我見過的許多實現,包括我們迄今為止開發的實現,都沒有考慮到一個重要的問題。當我們將元素的位置更改為fixed 時,它會離開頁面的流,因此下方的元素會“向上跳躍”大約等於元素高度的像素數(此“跳躍”的高度取決於邊距、邊框等)。

一個可能的解決方案是注入一個與我們想要“粘貼”的元素大小相同的佔位符元素,這樣當我們更新粘性元素的樣式時,就不會發生跳躍。此外,如果已設置正確的值,我們不想無緣無故地反復重新分配值。最後,我們想採用我使用 CSS 類描述的技術。

JavaScript 代碼的最終版本如下所示:

<code class="language-javascript">var menu = document.querySelector('.menu');
var menuPosition = menu.getBoundingClientRect();
var placeholder = document.createElement('div');
placeholder.style.width = menuPosition.width + 'px';
placeholder.style.height = menuPosition.height + 'px';
var isAdded = false;

window.addEventListener('scroll', function() {
    if (window.pageYOffset >= menuPosition.top && !isAdded) {
        menu.classList.add('sticky');
        menu.parentNode.insertBefore(placeholder, menu);
        isAdded = true;
    } else if (window.pageYOffset < menuPosition.top && isAdded) {
        menu.classList.remove('sticky');
        menu.parentNode.removeChild(placeholder);
        isAdded = false;
    }
});</code>

這是 sticky 類的聲明塊:

<code class="language-css">.sticky {
    top: 0;
    position: fixed;
}</code>

最終結果顯示在此下一個演示中:

CodePen 示例鏈接

現在您已經很好地掌握了問題是什麼以及可能的基於 JavaScript 的解決方案是什麼,是時候擁抱現代化並討論這個 position: sticky 是關於什麼了。

什麼是 position: sticky?

如果您勇敢地仔細閱讀了上一節,您可能想知道“瀏覽器為什麼不能為我做到這一點?”很高興您問!

sticky 是為 CSS position 屬性引入的一個新值。此值應該在其父元素內表現得像 position: static,直到達到給定的偏移閾值,在這種情況下,它就像值被設置為 fixed 一樣。換句話說,通過使用 position: sticky,我們可以無需 JavaScript 即可解決上一節中討論的問題。

回顧我們之前的示例並使用此新值,我們可以編寫:

<code class="language-css">.menu {
    margin: 0;
    padding: 0;
    width: 100%;
    background-color: #bffff3;
    position: sticky;
}</code>

瀏覽器將完成其餘工作!就這麼簡單。

瀏覽器支持和 Polyfills

目前對這個新值的支持非常糟糕。以下是每個瀏覽器的堆棧情況:

  • Firefox 26 – 通過在 about:config 下將 css.sticky.enabled 設置為“true”來支持。
  • Chrome 23 – 通過在 chrome://flags 中啟用“實驗性 Web 平台功能”來支持。
  • Chrome 38(?) – Chrome 團隊最近已從 Blink 中刪除此功能,因此它目前在 Chrome Canary(版本 38.x)中不可用,即使使用該標誌也是如此。您可以閱讀解釋刪除的錯誤報告,但我們懷疑此功能將很快重新實現,並且可能不會中斷穩定版本的支持。
  • Safari 6.1 – 使用 -webkit 供應商前綴支持該值(即 position: -webkit-sticky
  • Opera 23 – 通過在 about:flags 中啟用“實驗性 Web 平台功能”來支持。
  • Internet Explorer – 不支持(參見狀態)

有關所有詳細信息,請參見 Can I Use… 上的 position: sticky

幸運的是,有很多 polyfill 可供選擇:

  • Filament Group 的 fixed-sticky(需要 jQuery)
  • Matthew Phillips 的 position–sticky-(使用 Modernizr 進行檢測)
  • Philip Walton 的 Polyfill.js 庫中的 position: sticky
  • Fabrice Weinberg 的 position: sticky CodePen 演示(需要 jQuery)
  • Oleg Korsunsky 的 Stickyfill(IE9 )

演示

以下演示顯示了 position: sticky 的實際效果。如前所述,要使其工作,並且取決於您使用的瀏覽器,您可能需要激活一個標誌。

CodePen 示例鏈接

結論

儘管這項新功能沒有很好的瀏覽器支持,您可能也不願使用 polyfill,但如果使用 Modernizr 定義替代樣式,它將優雅地降級到默認的 position: staticposition: fixed

如果您嘗試過此屬性或知道任何其他 polyfill,請在評論中告訴我們。

關於 CSS Position Sticky 的常見問題解答 (FAQ)

CSS position sticky 與其他 CSS 位置有什麼區別?

CSS position: sticky 是相對定位和固定定位的混合體。它允許元素在其父元素內表現得像相對位置,直到達到給定的滾動點,此時它會變為固定位置。這與其他 CSS 位置不同。例如,“相對”位置允許您相對於元素的正常位置定位元素,而“固定”位置將元素相對於瀏覽器窗口定位,即使頁面滾動它也不會移動。 “絕對”位置將元素相對於最近的已定位祖先定位,“靜態”是默認值,並根據頁面的正常流程定位元素。

為什麼我的 CSS position sticky 不起作用?

您的 CSS position: sticky 不起作用可能有幾個原因。一個常見的原因是父元素的 overflow 屬性設置為 hiddenautoscroll。另一個原因可能是粘性元素有一個比它高的同級元素,導致它從視口中滾動出來。此外,請確保粘性元素不是表格元素,因為在某些瀏覽器中,CSS position: sticky 不適用於表格元素。

如何在我的所有瀏覽器上使 CSS position sticky 起作用?

雖然 CSS position: sticky 在現代瀏覽器中得到廣泛支持,但在某些舊版本中可能不起作用。為了確保跨所有瀏覽器的兼容性,您可以使用 polyfill。 polyfill 是一個提供您期望瀏覽器原生提供的技術的腳本。 CSS position: sticky 的一個流行 polyfill 是 Stickyfill。

我可以將 CSS position sticky 與其他 CSS 屬性一起使用嗎?

是的,您可以將 CSS position: sticky 與其他 CSS 屬性一起使用。例如,您可以將其與 z-index 一起使用來控制堆疊順序,或與 box-shadow 一起使用來在元素變為粘性時創建陰影效果。

CSS position sticky 在滾動容器中的行為如何?

當粘性元素位於滾動容器內時,當您向下滾動時,它會粘在容器的頂部,並且當容器的底部邊緣滾動過去時,它將停止粘性。

我可以在元素底部使用 CSS position sticky 嗎?

是的,您可以在元素底部使用 CSS position: sticky。您只需要為 bottom 屬性指定一個負值即可。這將使元素粘在容器的底部。

CSS position sticky 如何與邊距一起工作?

邊距與 CSS position: sticky 的工作方式與它們與相對定位一起工作的方式相同。邊距將相對於其粘性位置移動粘性元素,而不是其原始位置。

我可以將 CSS position sticky 用於水平滾動嗎?

是的,您可以將 CSS position: sticky 用於水平滾動。您只需要為 leftright 屬性指定一個值,而不是 topbottom 屬性。

如何使用 CSS position sticky 控制滾動偏移量?

滾動偏移量由 toprightbottomleft 屬性控制。您為這些屬性指定的值決定了元素開始粘貼的視口相應邊緣的距離。

我可以將 CSS position sticky 與 CSS 過渡一起使用嗎?

是的,您可以將 CSS position: sticky 與 CSS 過渡一起使用。但是,請記住,過渡僅在元素從相對位置更改為固定位置時才適用,而不是在它粘貼時。

請注意,我已將 CodePen 鏈接替換為佔位符,因為我無法訪問實際的 CodePen 示例。您需要替換這些佔位符為實際的鏈接。 此外,我盡可能地對原文進行了改寫,力求在不改變原意的情況下,使文章更流暢自然。

以上是CSS'位置:粘性” - 介紹和polyfills的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn