CSSでスクロールバーの有無によるがたつきをなくす2022年12月09日 09時42分

この記事はCSS Advent Calendar 2022の9日目の分です。


CSSのボックスモデルにおいては、ボーダーの内辺とパディングの外辺の間にスクロールバーが配置されます。最近はどのOSでもオーバーレイスクロールバー(スクロールバーが内容の前面に覆いかぶさるようなもの)が主流となり、スクロールバーが存在してもしなくても内容の幅が変わらないようになっています。一方、クラシックスクロールバー(スクロールバーが常に表示されるようなもの)が使われる環境では、overflow: autoな要素において内容がはみ出すときとはみ出さないときで内容の幅が変わってきます。

クラシックスクロールバーが使われる環境でも内容の幅を一定に保ちたいという場合は、scrollbar-gutterプロパティを使います。scrollbar-gutter: stableを指定すれば、スクロールバーが表示されないときでもスクロールバーと同じだけの領域が確保され、内容の幅はその分狭くなります。左右中央に配置したいのにスクロールバーの領域の分だけずれて困るというときは、scrollbar-gutter: stable both-edgesを指定することで、左右どちらにもスクロールバーと同じだけの領域が確保されます。

scrollbar-gutterプロパティの各値を指定した例

scrollbar-gutterプロパティを指定した効果の図

(上図はWindows 10 Firefox nightly 109.0a1での表示)

scrollbar-gutterプロパティはoverflow: hiddenな要素にも適用されますが、overflow: visibleな要素には適用されません。また、scrollbar-gutterプロパティの効果は、縦スクロールバー(縦書きなら横スクロールバー)にのみ影響します。

オーバーレイスクロールバーが使われる環境では、scrollbar-gutter: stableの効果はありません。

使用事例

使用事例としては、@about_hiroppyさんの紹介している「HTMLのdialog要素によるモーダルダイアログが開いているときに、背景の文書をスクロールさせない」というのが考えられます(scrollbar-gutterプロパティを指定した例指定しなかった例)。

html {
  scrollbar-gutter: stable;
}
html:has(dialog:modal) {
  overflow: hidden;
}

クラシックスクロールバーが使われる環境では、文書をスクロールさせないためにoverflow: hiddenを指定すると、スクロールバーが消えて文書の内容ががたついてしまいます。scrollbar-gutter: stableをあらかじめ指定しておけば、スクロールバーが消えてもその分の領域が確保され続けるので、文書の内容ががたつきません。