あなたのウェブサイトで跳ねるスクロール

公開: 2022-03-10
クイックサマリー↬この記事では、スクロールバウンスの効果と、さまざまなWebブラウザーでどのように機能するかについて説明します。 スクロールのバウンスを防ぐために使用できる、Web上で提案されているいくつかの異なるソリューションのレビューが含まれています。 この記事では、2017年12月にChromeで、2018年3月にFirefoxで実装されたCSSプロパティoverscroll-behaviorについても説明します。 この効果をよく理解することは、固定要素を持つWebサイトを構築または設計するのに非常に役立ちます。

スクロールバウンス(スクロール「ラバーバンディング」または「弾性スクロール」とも呼ばれる)は、ページまたはHTML要素の最上部、または最下部にスクロールしたときに表示される効果を指すためによく使用されます。タッチスクリーンまたはトラックパッドを使用するデバイス上のページまたは要素、および要素またはページが元に戻って上下に整列する前に、しばらくの間空のスペースが表示されます(タッチ/指を離したとき)。 要素間のCSSスクロールスナップでも同様の効果が発生することがわかります。

ただし、この記事では、Webページの最上部または最下部にスクロールしたときのスクロールバウンスに焦点を当てています。 つまり、スクロールポートがスクロール境界に達したときです。

データの収集、強力な方法

CSSを使用して統計を収集できることをご存知ですか? 実際、GoogleAnalyticsを使用してUIインタラクションを追跡するためのCSSのみのアプローチもあります。 関連記事を読む→

スクロールバウンスをよく理解すると、Webサイトの構築方法や、ページのスクロール方法を決定するのに役立ちます。

ページの移動でfixed要素を表示したくない場合は、スクロールバウンスは望ましくありません。 例としては、ヘッダーまたはフッターを特定の位置に固定する場合、メニューなどの他の要素を固定する場合、またはページをスクロールの特定の位置にスクロールスナップする場合、およびWebサイトへの訪問者を混乱させるような、ページの最上部または最下部で追加のスクロールが発生しないようにする必要があります。 この記事では、Webページの最上部または最下部でのスクロールバウンスを処理するときに直面する問題のいくつかの解決策を提案します。

ジャンプした後もっと! 以下を読み続けてください↓

効果との私の最初の出会い

ずっと前に作ったウェブサイトを更新していたときに、この効果に最初に気づきました。 あなたはここでウェブサイトを見ることができます。 ページ下部のフッターは、ページ下部の位置に固定されており、まったく動かないはずでした。 同時に、ページのメインコンテンツを上下にスクロールできるはずでした。 理想的には、次のように機能します。

macOS上のFirefoxでバウンスするスクロール
macOS上のFirefoxでバウンスするスクロール。 (大プレビュー)

現在、Firefoxまたはタッチスクリーンやトラックパッドのないデバイス上の任意のブラウザでこのように機能します。 しかし、当時、私はMacBookでChromeを使用していました。 ウェブサイトが正しく機能していないことに気付いたとき、トラックパッドを使用してページの一番下までスクロールしていました。 ここで何が起こったかを見ることができます:

macOSのChromeでバウンドするスクロール
macOSのChromeでバウンスするスクロール。 (大プレビュー)

大野! これは起こるはずだったものではありませんでした! CSSのpositionプロパティの値をfixedに設定して、フッターの位置をページの下部に設定しました。 これは、どのposition: fixed; は。 CSS 2.1仕様によると、「ボックス」(この場合は紺色のフッター)が固定されている場合、「ビューポートに対して固定されており、スクロールしても移動しません」。 これが意味するのは、ページを上下にスクロールしたときにフッターが移動することは想定されていなかったことです。 Chromeで何が起こっているのかを見たとき、これが私を心配させたものでした。

この記事をより完全にするために、モバイルエッジ、モバイルSafari、デスクトップSafariの両方でページがどのようにスクロールするかを以下に示します。 これは、FirefoxやChromeでのスクロールで発生することとは異なります。 これにより、まったく同じコードが現在さまざまな方法でどのように機能するかをよりよく理解できるようになることを願っています。 現在、さまざまなWebブラウザ間で同じように機能するスクロールを開発することが課題となっています。

macOSのSafariでバウンスするスクロール。 iOSのEdgeとSafariでも同様の効果が見られます
macOSのSafariでバウンスするスクロール。 iOSのEdgeとSafariでも同様の効果が見られます。 (大プレビュー)

解決策を探す

私の最初の考えの1つは、すべてのブラウザーでこの問題を修正する簡単で迅速な方法があるだろうということでした。 これが意味するのは、CSSコードを数行使用するソリューションを見つけることができ、JavaScriptが関与しないと思ったということです。 したがって、私が最初にしたことの1つは、これを達成しようとすることでした。 テストに使用したブラウザーには、macOSとWindows 10のChrome、Firefox、Safari、iOSのEdgeとSafariが含まれていました。 これらのブラウザのバージョンは、この記事の執筆時点(2018年)で最新のものでした。

HTMLおよびCSSのみのソリューション

絶対および相対ポジショニング

私が最初に試したことの1つは、このようなフッターの作成に慣れていたため、絶対位置と相対位置を使用してフッターを配置することでした。 Webページを100%の高さに設定して、フッターが常にページの下部に固定された高さになるようにします。コンテンツは100%からフッターの高さを引いたものになり、スクロールできます。 または、 calcを使用する代わりにpadding-bottomを設定し、アプリケーションのコンテンツがフッターと重ならないように、 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; )。 これと比較した場合のこのソリューションの利点の1つは、スクロールがページ全体ではなく、フッターのないページのコンテンツのみを対象としていることです。 この方法の最大の問題は、Mobile Safariでは、アプリケーションのフッターとコンテンツの両方が同時に移動することです。 これにより、すばやくスクロールするときにこのアプローチが非常に問題になります。

絶対および相対ポジショニング
絶対および相対ポジショニング。

私が望まなかったもう一つの影響は、最初は気付くのが難しく、それがもっと解決策を試した後に起こっていることに気づきました。 これは、アプリケーションのコンテンツをスクロールするのが少し遅いということでした。 スクロールコンテナの高さを100%に設定しているため、iOSでのフリック/モメンタムベースのスクロールが妨げられます。 その100%の高さが短い場合(たとえば、2000pxの100%の高さが900pxの100%の高さになる場合)、勢いに基づくスクロールは悪化します。 フリック/モメンタムベースのスクロールは、タッチスクリーンの表面を指でフリックすると、ページが自動的にスクロールするときに発生します。 私の場合、ユーザーがすばやくスクロールできるように、勢いに基づくスクロールを実行したかったので、高さを100%に設定するソリューションには近づきませんでした。

その他の試み

Webで提案され、コードで使用しようとしたソリューションの1つを、例として以下に示します。

 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では、フッターは表示されなくなります。

macOSSafariでフッターがありません
macOSSafariにフッターがありません。 (大プレビュー)

iOS Safariでは、フッターが短くなり、下部に余分な透明(または白)のギャップがあります。 また、一番下までスクロールすると、ページをスクロールする機能が失われます。 ここでフッターの下の白いギャップを見ることができます:

iOSSafariの短いフッター
iOSSafariの短いフッター。

よく目にする可能性のある興味深いコード行の1つは、次-webkit-overflow-scrolling: touch; 。 この背後にある考え方は、特定の要素に対して勢いに基づいたスクロールを可能にすることです。 このプロパティは、MDNドキュメントでは「非標準」および「標準トラック上にない」と説明されています。 FirefoxとChromeで検査中の「無効なプロパティ値」として表示され、DesktopSafariではプロパティとして表示されません。 最終的にこの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を使用する代替ソリューションがあるかどうかをすぐに確認しても問題はないと思いました。

タッチイベント

スクロールバウンスの問題を解決する1つのアプローチは、 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を使用しても違いはありません。 また、 touchstarttouchmoveの両方を使用してスクロールを制御しようとしましたが、これら2つの方法でも違いはありませんでした。 パフォーマンス上の理由から、この方法でevent.preventDefault()を呼び出すことはできなくなったことを学びました。 イベントリスナーでpassiveオプションをfalseに設定する必要があります。

 // Prevents window from moving on touch on newer browsers. window.addEventListener('touchmove', function (event) { event.preventDefault() }, {passive: false})

ライブラリ

「スクロール時にiOSWebアプリがバウンドするのを防ぐ」ために構築された「iNoBounce」というライブラリに出くわすかもしれません。 この記事で説明した問題を解決するためにこのライブラリを今すぐ使用するときに注意すべきことの1つは、 -webkit-overflow-scrollingを使用する必要があるということです。 もう1つ注意すべき点は、私が最終的に作成したより簡潔なソリューション(後で説明します)は、iOSの場合と同様のことを行うということです。 これは、GitHubリポジトリの例を見て、最終的に得たソリューションと比較することで、自分でテストできます。

オーバースクロール動作

これらのソリューションをすべて試した後、CSSプロパティoverscroll-behaviorについて知りました。 overscroll-behavior CSSプロパティは、2017年12月にChrome 63で、2018年3月にFirefox 59で実装されました。このプロパティは、MDNドキュメントで説明されているように、「ブラウザのスクロールオーバーフロー動作を制御できます。スクロールエリアに到達しました。」 これが私が最終的に使用したソリューションでした。

私がしなければならなかったのは、私のWebサイトのbodyoverscroll-behaviornoneに設定することだけで、フッターのpositionfixedのままにすることができました。 フッターのないコンテンツではなく、ページ全体に勢いに基づくスクロールが適用されたとしても、このソリューションは私にとって十分であり、その時点でのすべての要件を満たし、フッターがChromeで予期せずバウンドすることはなくなりました。 Edgeには、現在開発中としてフラグが立てられているこのプロパティがあることに注意してください。 overscroll-behaviorは、ブラウザーがまだサポートしていない場合、拡張機能と見なすことができます。

結論

固定されたヘッダーまたはフッターがWebページ上で跳ね返らないようにする場合は、 overscroll-behaviorプロパティを使用できるようになりました。

このソリューションはブラウザによって動作が異なりますが(SafariとEdgeではページコンテンツのバウンスが発生しますが、FirefoxとChromeでは発生しません)、一番上までスクロールするとヘッダーまたはフッターが固定されたままになります。またはWebサイトの下部。 これは簡潔なソリューションであり、テストされたすべてのブラウザーで、勢いに基づくスクロールが引き続き機能するため、多くのページコンテンツを非常にすばやくスクロールできます。 Webページに固定ヘッダーまたはフッターを作成している場合は、このソリューションの使用を開始できます。