在您的網站上滾動彈跳
已發表: 2022-03-10overscroll-behavior
於 2017 年 12 月在 Chrome 中實現,並於 2018 年 3 月在 Firefox 中實現,本文還介紹了該屬性。 很好地理解這種效果對於構建或設計任何具有固定元素的網站非常有幫助。滾動彈跳(有時也稱為滾動“橡皮筋”或“彈性滾動”)通常用於指您滾動到頁面或 HTML 元素的最頂部或底部時看到的效果頁面或元素,在使用觸摸屏或觸控板的設備上,並且在元素或頁面彈回並將其自身對齊回到其頂部/底部(當您釋放觸摸/手指時)之前,可以看到空白區域。 您可以在元素之間的 CSS 滾動捕捉中看到類似的效果。
但是,本文重點介紹當您滾動到網頁的最頂部或最底部時的滾動彈跳。 換句話說,當滾動端口到達其滾動邊界時。
收集數據,強大的方式
你知道 CSS 可以用來收集統計數據嗎? 事實上,甚至還有一種僅使用 CSS 的方法來使用 Google Analytics 跟踪 UI 交互。 閱讀相關文章 →
很好地理解滾動彈跳非常有用,因為它將幫助您決定如何構建您的網站以及您希望頁面如何滾動。
如果您不想在頁面移動時看到fixed
元素,則不希望滾動彈跳。 一些示例包括:當您希望將頁眉或頁腳固定在某個位置時,或者如果您希望任何其他元素(例如菜單)被固定,或者如果您希望頁面在滾動時的某些位置滾動對齊,並且您不希望在頁面的最頂部或底部發生任何額外的滾動,這會使您網站的訪問者感到困惑。 本文將針對在處理網頁頂部或底部的滾動彈跳時所面臨的問題提出一些解決方案。
我第一次遇到效果
當我更新我很久以前建立的網站時,我首先註意到了這種效果。 你可以在這裡查看網站。 頁面底部的頁腳應該固定在頁面底部的位置並且根本不動。 同時,您應該能夠上下滾動頁面的主要內容。 理想情況下,它會像這樣工作:
它目前在 Firefox 或沒有觸摸屏或觸控板的設備上的任何瀏覽器中以這種方式工作。 但是,當時我在 MacBook 上使用 Chrome。 當我發現我的網站無法正常工作時,我正在使用觸控板滾動到頁面底部。 你可以看到這裡發生了什麼:
不好了! 這不是應該發生的事情! 通過將其 CSS position
屬性設置為fixed
,我將頁腳的位置設置為頁面底部。 這也是重新審視什麼position: fixed;
是。 根據 CSS 2.1 規範,當“框”(在本例中為深藍色頁腳)固定時,它“相對於視口是固定的,並且在滾動時不會移動”。 這意味著當您上下滾動頁面時,頁腳不應該移動。 當我看到 Chrome 上發生的事情時,這讓我很擔心。
為了使本文更完整,我將在下面向您展示頁面如何在 Mobile Edge、Mobile Safari 和 Desktop Safari 上滾動。 這與在 Firefox 和 Chrome 上滾動時發生的情況不同。 我希望這能讓您更好地了解完全相同的代碼當前如何以不同的方式工作。 目前,開發在不同 Web 瀏覽器上以相同方式工作的滾動是一項挑戰。
尋找解決方案
我的第一個想法是,將有一種簡單快捷的方法來解決所有瀏覽器上的這個問題。 這意味著我認為我可以找到一個只需要幾行 CSS 代碼並且不涉及 JavaScript 的解決方案。 因此,我做的第一件事就是嘗試實現這一目標。 我用於測試的瀏覽器包括 macOS 和 Windows 10 上的 Chrome、Firefox 和 Safari,以及 iOS 上的 Edge 和 Safari。 這些瀏覽器的版本是撰寫本文時的最新版本(2018 年)。
僅 HTML 和 CSS 解決方案
絕對和相對定位
我嘗試的第一件事是使用絕對和相對定位來定位頁腳,因為我習慣於這樣構建頁腳。 我的想法是將我的網頁設置為 100% 的高度,以便頁腳始終位於頁面底部並具有固定的高度,而內容佔用 100% 減去頁腳的高度,您可以滾動瀏覽它。 或者,您可以設置padding-bottom
而不是使用calc
並將body-container
高度設置為 100%,這樣應用程序的內容就不會與頁腳重疊。 CSS 代碼看起來像這樣:
html { width: 100%; height: 100%; overflow: hidden; position: relative; } body { width: 100%; margin: 0; font-family: sans-serif; height: 100%; overflow: hidden; } .body-container { height: calc(100% - 100px); overflow: auto; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: absolute; bottom: 0; height: 100px; width: 100%; }
該解決方案的工作方式與原始解決方案幾乎相同(只是position: fixed;
)。 與此相比,此解決方案的一個優點是滾動不是針對整個頁面,而是僅針對沒有頁腳的頁面內容。 這種方法最大的問題是在 Mobile Safari 上,應用程序的頁腳和內容同時移動。 這使得這種方法在快速滾動時非常有問題:
另一個我不想要的效果一開始很難注意到,我只是在嘗試了更多的解決方案後才意識到它正在發生。 這是因為滾動瀏覽我的應用程序的內容稍微慢了一點。 因為我們將滾動容器的高度設置為自身的 100%,這會阻礙 iOS 上基於輕彈/動量的滾動。 如果該 100% 高度更短(例如,當 2000 像素的 100% 高度變為 900 像素的 100% 高度時),基於動量的滾動會變得更糟。 當您用手指輕拂觸摸屏表面並且頁面自行滾動時,就會發生基於輕拂/動量的滾動。 在我的例子中,我希望發生基於動量的滾動,以便用戶可以快速滾動,所以我遠離將高度設置為 100% 的解決方案。
其他嘗試
網絡上建議的解決方案之一,我嘗試在我的代碼中使用,如下所示作為示例。
html { width: 100%; position: fixed; overflow: hidden; } body { width: 100%; margin: 0; font-family: sans-serif; position: fixed; overflow: hidden; } .body-container { width: 100vw; height: calc(100vh - 100px); overflow-y: auto; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 10px; } footer { position: fixed; bottom: 0; height: 100px; width: 100%; }
此代碼在 macOS 上的 Chrome 和 Firefox 上的工作方式與之前的解決方案相同。 這種方法的一個優點是滾動不限於 100% 高度,因此基於動量的滾動可以正常工作。 然而,在 Safari 上,頁腳消失了:
在 iOS Safari 上,頁腳變短,底部有一個額外的透明(或白色)間隙。 此外,滾動到最底部後,滾動頁面的能力將丟失。 您可以在此處看到頁腳下方的白色間隙:
您可能會看到很多有趣的代碼行: -webkit-overflow-scrolling: touch;
. 這背後的想法是它允許對給定元素進行基於動量的滾動。 此屬性在 MDN 文檔中被描述為“非標準”和“不在標準軌道上”。 它在 Firefox 和 Chrome 中顯示為正在檢查的“無效屬性值”,並且在桌面 Safari 中不顯示為屬性。 最後我沒有使用這個 CSS 屬性。
為了展示您可能遇到的另一個解決方案示例以及我發現的不同結果,我還嘗試了以下代碼:
html { position: fixed; height: 100%; overflow: hidden; } body { font-family: sans-serif; margin: 0; width: 100vw; height: 100vh; overflow-y: auto; overflow-x: hidden; -webkit-overflow-scrolling: touch; } .color-picker-main-container { width: 100%; font-size: 22px; padding-bottom: 110px; } footer { position: fixed; }
這實際上適用於不同的桌面瀏覽器,基於動量的滾動仍然有效,並且頁腳固定在底部並且不會在桌面 Web 瀏覽器上移動。 也許這個解決方案最有問題的部分(以及它的獨特之處)是,在 iOS Safari 上,頁腳總是會輕微晃動和扭曲,並且您可以在滾動時看到其下方的內容。
使用 JavaScript 的解決方案
在嘗試了一些僅使用 HTML 和 CSS 的初始解決方案後,我嘗試了一些 JavaScript 解決方案。 我想補充一點,我不建議您這樣做,最好避免這樣做。 根據我的經驗,通常有更優雅和簡潔的解決方案只使用 HTML 和 CSS。 但是,我已經花了很多時間嘗試其他解決方案,我認為快速查看是否有使用 JavaScript 的替代解決方案不會有什麼壞處。
觸摸事件
解決滾動彈跳問題的一種方法是阻止window
或document
上的touchmove
或touchstart
事件。 這背後的想法是阻止整個窗口上的觸摸事件,而允許您要滾動的內容上的觸摸事件。 像這樣的代碼示例如下所示:
// Prevents window from moving on touch on older browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, false) // Allows content to move on touch. document.querySelector('.body-container').addEventListener('touchmove', function (event) { event.stopPropagation() }, false)
我嘗試了此代碼的許多變體以嘗試使滾動正常工作。 阻止window
上的touchmove
沒有任何區別。 使用document
沒有任何區別。 我也嘗試使用touchstart
和touchmove
來控制滾動,但這兩種方法也沒有區別。 我了解到,出於性能原因,您不能再以這種方式調用event.preventDefault()
。 您必須在事件偵聽器中將passive
選項設置為false
:
// Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})
圖書館
您可能會遇到一個名為“iNoBounce”的庫,該庫旨在“阻止您的 iOS Web 應用在滾動時彈跳”。 現在使用這個庫來解決我在本文中描述的問題時需要注意的一點是,它需要您使用-webkit-overflow-scrolling
。 另一件需要注意的事情是,我最終得到的更簡潔的解決方案(稍後將描述)與 iOS 上的功能類似。 您可以通過查看其 GitHub 存儲庫中的示例來自行測試,並將其與我最終得到的解決方案進行比較。
過度滾動行為
在嘗試了所有這些解決方案之後,我發現了 CSS 屬性overscroll-behavior
。 overscroll-behavior
CSS 屬性於 2017 年 12 月在 Chrome 63 和 2018 年 3 月在 Firefox 59 中實現。如 MDN 文檔中所述,此屬性“允許您控制瀏覽器的滾動溢出行為——當已到達滾動區域。” 這是我最終使用的解決方案。
我所要做的就是在我的網站body
中將overscroll-behavior
設置為none
,然後我可以將頁腳的position
保留為fixed
。 儘管基於動量的滾動應用於整個頁面,而不是沒有頁腳的內容,但這個解決方案對我來說已經足夠好了,並且滿足了我當時的所有要求,並且我的頁腳不再在 Chrome 上意外反彈。 值得注意的是,Edge 現在將此屬性標記為正在開發中。 如果瀏覽器尚不支持overscroll-behavior
,則可以將其視為一種增強。
結論
如果您不希望您的固定頁眉或頁腳在您的網頁上反彈,您現在可以使用overscroll-behavior
CSS 屬性。
儘管該解決方案在不同瀏覽器中的工作方式不同(頁面內容的彈跳仍然會在 Safari 和 Edge 上發生,而在 Firefox 和 Chrome 上則不會),但當您滾動到最頂部時,它會保持頁眉或頁腳不變或網站底部。 這是一個簡潔的解決方案,在所有經過測試的瀏覽器上,基於動量的滾動仍然有效,因此您可以非常快速地滾動瀏覽大量頁面內容。 如果您要在網頁上構建固定的頁眉或頁腳,則可以開始使用此解決方案。