CSSのみでスクロールバーの幅を取得する方法

コンテナクエリ単位の登場により、これまでJavaScriptに頼ることが多かった計算も、CSSだけで行えるようになってきました。

この記事では、その仕組みを使ってCSSのみでスクロールバーの幅を取得する方法を紹介します。

目次

最小構成

CSSのみでスクロールバーの幅を取得するための最小構成です。

@property --scrollbar-width {
  syntax: "<length>";
  inherits: true;
  initial-value: 0px; 
}

html {
  container-type: inline-size;
}

body {
  --scrollbar-width: calc(100vw - 100cqi);
}

ポイントは、100vwとコンテナクエリ単位の100cqiを比較している点です。
(※cqiの代わりにcqwでも可)

100vwはスクロールバーを含んだビューポート幅、100cqiはスクロールバーを除いた表示領域の幅になるため、その差分がスクロールバーの幅になります。

ここではその差を--scrollbar-widthというカスタムプロパティに格納しています。

フルブリードレイアウトのデモ

スクロールバーの幅が必要になる代表的なケースとして、親要素の幅を超えて画面幅いっぱいに表示するフルブリードレイアウトが挙げられます。

See the Pen CSSのみでスクロールバーの幅取得 by hisa (@hisaaashi) on CodePen.

単純に100vwを指定した場合は、横スクロールが発生してしまいますが、スクロールバーを考慮して計算すると画面幅ぴったりに収めることができます。

とはいえ…

フルブリードレイアウトの実装ならcqiをそのまま使うこともできます。

html {
  container-type: inline-size;
}

body {
  --fullwidth-half: 50cqi;
}

.fullwidth-section {
  margin-inline: calc(50% - var(--fullwidth-half));
}

See the Pen CSSのみでスクロールバーの幅取得 by hisa (@hisaaashi) on CodePen.

ただし、コンテナクエリ単位は「最も近い祖先のコンテナ」 を基準とするので、上記アプローチはコンテナ要素がネストしていないことが条件です。

html {
  container-type: inline-size;
}

body {
  --fullwidth-half: 50cqi;
}

main {
  container-type: inline-size; /* ネスト */
  max-width: 600px;
  margin-inline: auto;
}

.fullwidth-section {
  /* 🙅 main 要素の 50cqi を基準に計算される */
  margin-inline: calc(50% - var(--fullwidth-half));
}

コンテナクエリの注意点

コンテナクエリは強力ですが、古いバージョンのブラウザではいくつかのバグが報告されています。

  • コンテナ要素の子孫要素でposition: fixedが効かずabsoluteとして扱われる
  • Safariでhtml要素に指定したcontainer-typeが正しく機能しない

現在この問題は改善されていますが、必要に応じてフォールバックを用意するか、あるいは最新のOSやブラウザのみを対象として要件定義しておいた方が安全です。

まとめ

CSSだけでスクロールバーの幅を取得する方法の解説でした。

JavaScriptを使用しない一つの選択肢として覚えておくと便利です。

カスタマイズに困ったらお気軽にご相談を!

  • 「ちょっとしたCSSの調整だけお願いしたい」
  • 「不具合を直してほしい」

料金は3,000円〜、お支払いは銀行振込・Amazonギフトカードなど柔軟に対応してます🤔

役に立ったら他の方にシェア

お気軽にコメントどうぞ

コメントする

目次