【jQuery】スクロールバーの横幅を取得してCSS変数で管理する方法

技術

CSSで画面いっぱいに要素を広げたい時、width: 100vw; を使うと、なぜか横スクロールが出て画面がガタついた経験はありませんか?

実はこれ、100vw が「スクロールバーの幅」を含んでしまうことが原因。ブラウザやOSによってスクロールバーの有無や幅が異なるため、CSSだけで完璧に制御するのは至難の業です。

そこで今回は、jQueryを使ってスクロールバーの正確な幅を計測し、CSS変数(カスタムプロパティ)に受け渡す方法を解説します。これさえ覚えれば、もう画面の横揺れに悩まされることはありません!

なぜスクロールバーの幅が必要なのか?(100vwの罠)

多くのブラウザにおいて、100vw はスクロールバーの厚みを含んだサイズを指します。 しかし、コンテンツの表示領域は「100vw – スクロールバーの幅」となるため、単純に 100vw を指定すると、スクロールバーの分だけ要素がはみ出してしまい、不要な横スクロールが発生してしまいます。

この「スクロールバーの幅」をJSで数値として取得できれば、CSS側で計算(calc)に使えるようになり、正確なレイアウトが可能になります。

【重要】スクロールバーの幅を取得するコード

jQueryを使って、目に見えない一時的な要素を作成し、その差分からスクロールバーのサイズを算出します。

$(function() {
  /*-------------------------------------------
   スクロールバーの幅取得
  --------------------------------------------*/
  function getScrollbarSize() {
    // 1. 一時的なdiv要素を作成して、強制的にスクロールバーを出す
    const $div = $("<div></div>")
      .css({
        position: "absolute",
        width: "100px",
        height: "100px",
        visibility: "hidden",
        overflow: "scroll", // 常にスクロールバーを表示
      })
      .appendTo("body");

    // 2. 「コンテンツの外側」と「コンテンツの内側」の差分を計算
    const scrollbarWidth = $div.outerWidth() - $div[0].clientWidth;

    // 3. 計算が済んだらdiv要素を削除
    $div.remove();

    return scrollbarWidth;
  }

  // 実行してCSS変数(--scrollbar-width)に代入
  const scrollbarWidth = getScrollbarSize();
  $("html").css("--scrollbar-width", scrollbarWidth + "px");
});

やっていることの解説

  1. ダミー要素の作成: 画面外に100pxの正方形を作ります。
  2. スクロールバーの算出: スクロールバーを除いた内側の幅 clientWidth を引くことで、「スクロールバーの横幅」を割り出します。
  3. CSS変数へのセット: 取得した数値を --scrollbar-width という名前でCSS変数に登録します。

CSS側での使い方

JSから受け取った変数を、CSSの calc() 関数の中で利用します。

:root {
  /* 初期値を設定(JSが動く前の保険) */
  --scrollbar-width: 0px;
}

.full-width {
  /* スクロールバーを除いた、本当の画面いっぱいの幅を計算 */
  width: calc(100vw - var(--scrollbar-width));
}

このように、100vw からJSで取得した --scrollbar-width を引くことで、どんな環境でもスクロールバーが出ない、ピッタリ画面内に収まるフルワイド要素が作れます。

まとめ

スクロールバーの幅は、WindowsかMacか、あるいはブラウザの設定によってバラバラです。 今回の方法を使えば、環境に左右されず、常に正確な画面幅を計算できるようになります。

ぜひこのテクニックを活用してみてください。