≪ Today I learned.
RSS購読
    公開日
    タグ
    CSS
    著者
    ダーシノ

    スクロールバーとOSの外観設定

    ボタン付きのスタック型のコンポーネントで、スタック要素にスクロールバーが表示されるとき、OSの外観設定によってスタイルが崩れてしまう。

    以下のようにスクロールバーが表示されることで、Scrollable AreaとButtonの幅がズレてしまう。

    +----------------------------+
    |           Button           |
    +-------------------------+--+
    |                         |  |
    | <-- Scrollable Area --> |  |
    |                         |  |
    |                         |  |
    |                         |  |
    +-------------------------+--+
                     Scrollbar ┘

    これはOSの外観設定でスクロールバーの表示/非表示(オーバーレイ)によるものだ。

    macOSの外観設定。「スクロールバーを表示」という項目に、「マウスまたはトラックパッドに基づいて自動的に表示」「スクロール時に表示」「常に表示」の選択肢がある。

    ブラウザ標準の挙動

    「常に表示」の場合は、要素のwidthにスクロールバーの幅が含まれるのに対し、「スクロール時に表示」では含まれない。

    ▶常に表示の場合
    +----------------------------+
    |           Button           |
    +-------------------------+--+
    |                         |  |
    | <-- Scrollable Area --> |  |
    |                         |  |
    |                         |  |
    |                         |  |
    +-------------------------+--+
                     Scrollbar ┘
    ▶スクロール時に表示の場合
    +----------------------------+
    |           Button           |
    +----------------------------+
    |                            |
    | <--- Scrollable Area ----> |
    |                            |
    |                            |
    |                            |
    +----------------------------+

    scrollbar-gutterを使った場合

    scrollbar-gutterプロパティを使うことで、スクロールバーの幅をあらかじめ確保できるが、そうすると「スクロール時に表示」のときに余分なスペースができてしまう。

    ▶常に表示の場合
    +----------------------------+
    |           Button           |
    +-------------------------+--+
    |                         |  |
    | <-- Scrollable Area --> |  |
    |                         |  |
    |                         |  |
    |                         |  |
    +-------------------------+--+
                     Scrollbar ┘
    ▶スクロール時に表示の場合
    +----------------------------+
    |           Button           |
    +-------------------------+--+
    |                         |
    | <-- Scrollable Area --> |
    |                         |
    |                         |
    |                         |
    +-------------------------+
               scrollbar-gutter ┘

    デモ

    • xxxx
    • xxxx

    scrollbar-gutter: autoの場合

    スクロールが発生すると内包される要素が縮む

    scrollbar-gutter: stableの場合

    スクロールが発生する前から内包される要素が縮んでいる

    まとめ

    ユーザー環境に左右されない実装方法として、scrollbar-width: noneを使ってスクロールバー自体を再実装する方法がある。“技術的には可能”だがなるべくやりたくない手法だ。

    したがって、スクロールバーによるコンテンツの幅が変わる現象は「ユーザー環境によるもの」と割り切ってブラウザのデフォルトの挙動に寄せるのが良いと思う。