代表的な面接トピック

スクロールバーに起因するレイアウトシフトを防ぐために scrollbar-gutter をどのように使用しますか?

フロントエンド普通
Offer.cc 編集チーム公開日 更新日

質問

中央揃えの管理画面で、モーダルが開いたときや長い検索結果がオーバーフローし始めたときに水平方向に画面がガタつきます(ジャンプします)。scrollbar-gutter をどのように使用し、オーバーレイスクロールバー(overlay scrollbars)、RTL、モーダルのスクロールロック、およびレガシーブラウザをどのように処理しますか?

質問とシナリオ

ページは overflow: auto を使用しています。ユーザー操作前はオーバーフローがなく、その後クラシックスクロールバーが表示されます。スクロールバーがインライン空間を消費するため、中央揃えのコンテンツが移動してしまいます。CSSの設計、その適用境界、フォールバックの動作、および測定可能な検証について説明してください。

面接官がテストしていること

  • scrollbar-gutter がスクロールボックスに適用され、継承されないプロパティであることを理解しているか。
  • クラシックスクロールバーとオーバーレイスクロールバーを区別し、stableboth-edges の違いを説明できるか。
  • ルート、body、およびネストされたスクローラー間のスコープの違いを理解しているか。
  • モーダルのロック、RTL、レガシーブラウザ、およびCLSモニタリングが計画に含まれているか。

最初に確認すべき明確化の質問

ガタつきがビューポートで発生しているのか、内部スクローラーで発生しているのか、OSがオーバーレイスクロールバーを使用しているか、RTLが必要か、モーダルがページのスクロールをどのようにロックしているか、対象となるブラウザやアクセシビリティの目標は何かを確認します。また、レイアウトを幾何学的に中央揃えのまま維持する必要があるのか、オーバーフロー開始時の片側への移動を防ぐだけでよいのかを質問します。

30秒で答えるフレームワーク

オーバーフローの前後でクラシックスクロールバーの領域が存在するように、実際にスクロールするボックスに scrollbar-gutter: stable を指定します。対称的な中央揃えが重要な場合は stable both-edges を使用します。ビューポートのスクロール用にはルートを設定し、内部パネルにはそれぞれのスクロールを設定します。オーバーレイスクロールバーは通常レイアウト空間を消費しないため、固定幅を予約する必要はありません。モーダルロック、RTL、レガシー向けフォールバックを明確に維持し、レイアウトシフトの計測と実機マトリックスで検証します。

ステップバイステップの詳細解説

  1. スクロールボックスを特定する。 ルートがビューポートのスクロールを制御します。body 宣言はルートの動作の代わりにはなりません。独立してスクロールするパネルには独自の宣言が必要です。
  2. 値を選択する。 stable はクラシックスクロールバー用のインライン空間を予約します。both-edges は反対側の端にも同じガターを追加して、幾何学的な中央揃えを維持します。
  3. オーバーレイを理解する。 オーバーレイスクロールバーはコンテンツの上に重なって表示され、通常はレイアウト空間を消費しません。ユーザーエージェントとOSがモードを選択するため、CSSでクラシックスクロールバーを強制することはできません。
  4. モーダルと協調させる。 ページのスクロールのロックと復元には単一のステートマシンを使用します。ブラウザが予約したガターの上に無条件で padding-right を追加しないようにします。モーダル内部のスクローラーは別途設定します。
  5. 互換性とRTLを網羅する。 モダンブラウザでは論理インラインプロパティを使用し、レガシー環境向けには最小限のフォールバックを維持し、書字方向、スクロールバーの位置、セーフエリアをテストします。
  6. 結果を測定する。 layout-shift のパフォーマンスエントリを記録し、ユーザー入力前後のシフトを区別し、長いリスト、モーダル、低速ネットワークのラボテストとフィールドのp75データを組み合わせます。良好なCLSターゲットはp75で0.1以下です。

質の高い模範解答

実際にスクロールするボックスに対して宣言します:

css
html {
  scrollbar-gutter: stable both-edges;
}

.results-pane {
  overflow: auto;
  scrollbar-gutter: stable;
}

stable はオーバーフローがない状態でもクラシックスクロールバーの領域を確保し続けます。both-edges はビューポート中央揃えのレイアウトの対称性を維持します。システムがオーバーレイスクロールバーを使用している場合、それらは最初からレイアウト空間を消費しないため、固定ピクセルの予約は約束しません。モーダルを開く際、無条件で別のスクロールバー幅補正を追加することはしません。ロックのステートマシンとガターポリシーを一致させ、モーダル内部のスクローラーは個別に設定します。

ルートと body の違い、ネストされたスクローラー、RTL、閉じた後の復元、レガシーブラウザ向けフォールバック、および視覚効果抑制(reduced-motion)の設定を検証します。layout-shift エントリとフィールドp75のCLSを収集し、p75 CLS 0.1以下を目標とします。MDNおよびW3C仕様がプロパティのセマンティクスを定義し、web.devがCLS測定モデルを提供しています。

よくある間違い

  • どの要素が実際にスクロールするかを確認せずに、通常の親要素に scrollbar-gutter を指定すること。
  • body の宣言が必ずビューポートを制御すると誤認し、ルートの挙動を無視すること。
  • オーバーレイスクロールバーに対して固定ピクセルの領域予約を前提とすること。
  • stable を有効にしつつ、無条件に padding-right も追加してしまい、モーダルが開いたときに二重の余白を作ってしまうこと。
  • CLSや内部パネルを測定せず、単一のOSかつRTL無しのスクリーンショットのみでテストすること。

フォローアップ質問と回答

なぜ both-edges を使うのですか?

片側の stable は、クラシックスクロールバーが表示されるインライン側の端を予約します。コンテンツがビューポートの中央に配置されている場合、反対側の端に同じガターを設けることで幾何学的な対称性が維持されます。それでも、RTLや異なるスクロールバー配置のテストは必要です。

scrollbar-gutter はすべてのモーダルスクロールロックの問題を解決しますか?

いいえ。スクロールボックスのレイアウト空間を予約するだけであり、フォーカストラップ、背景の操作無効化(inertness)、スクロール位置の復元、重なり順(スタッキング順)などは実装しません。これらは別の責務として残り、ロック処理によって幅の補正を重複させてはなりません。

オーバーレイスクロールバーとクラシックスクロールバーをどのようにテストしますか?

少なくとも1つのクラシックスクロールバー環境と1つのオーバーレイスクロールバー環境を使用します。オーバーフローなし、オーバーフロー開始時、モーダルの開閉、内部パネルのスクロール、RTL、ズームをテストします。スクリーンショットだけに依存せず、主要要素の幾何学的配置と layout-shift エントリを記録します。

公開情報ソース

関連する質問