2022年9月にSafari 16がリリースされ、すべての主要なブラウザで、CSSのoverscroll-behavior
プロパティが利用可能になりました。ChromeやFirefoxでは、2018年3月からサポートされていたプロパティだったので、耳にしたことがある方も多いのではないでしょうか?
overscroll-behavior
プロパティは、スクロール可能なコンテンツ(以下、スクロールコンテナー)を端までスクロールした時の動作を制御できるプロパティです。このプロパティを利用することで次のような問題を解決できます。
- 背面のコンテンツにスクロールが伝達する動作を抑制する
- ダイアログやハンバーガーメニューといった、画面固定したコンテンツをスクロールする場合も、背面がスクロールされる問題を防ぐ
- ブラウザのPull-to-Refresh(ブラウザを上方向にスワイプしてリロードする)を抑制する
画面固定したコンテンツで背面がスクロールされる問題は、『HTMLでモーダルUIを作るときに気をつけたいこと』でも取り上げていて、JavaScriptで制御する対策を紹介しました。同じ問題をoverscroll-behavior
プロパティでよりシンプルに解決できるようになります。
本記事では、overscroll-behavior
プロパティで制御できる動作と使い方について紹介します。
overscroll-behaviorとは
overscroll-behavior
は、スクロールコンテナーを境界(端)までスクロールしたあと、さらに同じ方向にスクロールした時の動作を制御するプロパティです。
動作は大きく2つに分類されます。ひとつは背面にスクロールコンテナーがあれば、背面にスクロールが伝達するスクロールチェーンと呼ばれる動作です。もうひとつはPull-to-Refresh(ブラウザを上方向にスワイプしてリロードする)といった、オーバースクロール(スクロール可能な領域を少し超えて行われること)の動作です。
▼背面のコンテンツにスクロールが伝達される例
▼Pull-to-Refreshの例
スクロール可能なコンテンツでプロパティを利用できる
overflow
プロパティのようにx軸、y軸をそれぞれ制御するoverscroll-behavior-x
とoverscroll-behavior-y
というプロパティが存在し、2つの軸を制御するoverscroll-behavior
プロパティがあります。
overflow: auto
およびoverflow: scroll
が指定されたスクロールコンテナーに対してoverscroll-behavior
プロパティを指定することで適用されます。
overflow
プロパティが設定されていた場合でも、スクロールバーが発生しないスクロール不可能な要素だった場合は、overscroll-behavior
プロパティは無視されます。
▼overscroll-behavior
が適用される例
<div class="container">
<div class="item"></div>
</div>
.container {
width: 100px;
height: 25px; /* 親要素が子要素より小さくスクロール可能 */
overflow-y: auto;
overscroll-behavior-y: none; /* 適用される */
}
.item {
width: 100%;
height: 50px;
}
▼スクロール不可能なため、overscroll-behavior
が無視される例
<div class="largeContainer">
<div class="item"></div>
</div>
.largeContainer {
width: 100px;
height: 100px; /* 親要素が子要素より大きくスクロール不可能 */
overflow-y: auto;
overscroll-behavior-y: none; /* 無視される */
}
.item {
width: 100%;
height: 50px;
}
値の初期値にはauto
が指定され、contain
またはnone
で制御する
overscroll-behavior
の値は、auto | contain | none
の3つが存在します。初期値にはauto
が指定されます。
値 | 説明 |
---|---|
auto | スクロールチェーンやオーバースクロールは、デフォルトの動作を行います。 |
contain | スクロールチェーンを抑制し、オーバースクロールの動作を維持します。 |
none | スクロールチェーンと、オーバースクロールの動作を抑制します。 |
3つ値の具体的な動作は、次のサンプルで確認できます。overscroll-behavior
プロパティがcontain
またはnone
だった場合、背面のコンテンツにスクロールが伝達しないことを確認できます。
加えてcontain
は、オーバースクロールの動作を維持します。このサンプルでは、コンテンツを超えて上下にバウンスする効果を確認できます。(次のGIF画像の2番目)
効果が有効かどうかは、OSやブラウザによって異なりますが、モバイルのPull-to-Refreshが有効なブラウザから確認できると思います。
- サンプルを別ウインドウで開く
- コードを確認する(HTML、CSS)
どのような使い方ができるのか、作例をいくつか用意しましたのでご紹介します。実装の参考にしてみてください。
画面固定で表示するUIの作例
画面固定で表示されるダイアログとハンバーガーメニューをdialog
要素で実装し、overscroll-behavior: contain
で制御した作例です。
表示されるコンテンツを画面サイズにして、背景を含めたスクロール制御をしています。また、表示されるコンテンツをスクロール可能なサイズにしなければoverscroll-behavior
プロパティは適用されないため、縦幅をheight: calc(100% + 1px);
として1pxだけスクロールできるように調整しています。
- サンプルを別ウインドウで開く
- コードを確認する(HTML、CSS)
ハンバーガーメニューをdialog
要素で実装しているのは、少し変わったアプローチかもしれませんが、キーボード操作を考慮するために使用しています。詳しく知りたい方は、次の記事も参考にしてみてください。
ルート要素を制御する作例
ルートとなる要素にoverscroll-behavior
プロパティを指定することも可能です。次の作例では、overscroll-behavior-y: none
を指定しています。ブラウザのPull-to-Refreshが確認できるデバイスで見ると、Pull-to-Refreshが抑制されていることを確認できます。
ブラウザごとにoverscroll-behavior
プロパティを指定するルートの要素が異なります。ChromeやEdgeなどChromium系のブラウザでは、body
要素を指定して、SafariやFirefoxではhtml
要素に指定することで動作します。
html,
body {
overscroll-behavior-y: none;
}
iframe要素は、ブラウザによって異なる動作をするので注意
最後に、iframe
要素にoverscroll-behavior: none
を設定した作例を紹介します。この作例はChromeやEdgeなどChromium系のブラウザでのみ動作します。
MDNのドキュメントでは、iframe
要素はスクロールコンテナーではないため、overscroll-behavior
プロパティでスクロールを制御できないという説明があります。実際にSafariやFirefoxでは動作せず、ブラウザによって異なる動作をするため注意が必要です。
- サンプルを別ウインドウで開く
- コードを確認する(HTML、CSS)
ブラウザのサポート状況
Can I use…によると、Chrome、Firefox、Safari、Edgeの最新バージョンで利用可能と記載されています。
▲Chrome 65(2018年3月)以上、Edge 79(2020年1月)以上、Safari 16.0(2022年9月)以上、Firefox 59(2018年3月)以上でサポートされています。
まとめ
overscroll-behavior
プロパティで制御できる動作や使い方の紹介をしました。とくにスクロールチェーンの制御は、これまではbody
要素にoverflow: hidden
を追加したり、JavaScriptで制御するなど一工夫が必要でした。ですが、overscroll-behavior
プロパティを利用することでシンプルに制御できるようになります。
実務でも画面固定のUIは実装する機会が多いので、overscroll-behavior
プロパティが役立つでしょう。