CSSで、スクロールバーの見た目を変える方法

​​CSS​HTML,Playwright,アクセシビリティ

スクロールバーの色は scrollbar-color、太さは scrollbar-width の2つのプロパティで変えられます。つまみを丸くしたり、太さをpx単位で決めたりしたいときは、::-webkit-scrollbar などの擬似要素を使います。ただし、この2つのやり方を同じ要素に混ぜると、Chromium では擬似要素の指定がまるごと無視されます。

補足

検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。Playwright でページを開き、スクロールバーの太さ(offsetWidth から clientWidth と左右の枠を引いた値)と、スクリーンショットの画素の色を読みました。Playwright は Chromium を --hide-scrollbars 付きで起動し、そのままでは太さが0pxになったので、この引数を外して測っています。Firefox と Safari、Windows と macOS、スマートフォンのスクロールバーは試していません。

スクロールできる同じリストの箱を3つ、縦に並べた画像。上の「何も指定しない」では、右端に灰色のつまみと、上下に小さな三角の矢印がある太めのスクロールバーが出ている。真ん中の「scrollbar-color と scrollbar-width: thin」では、細いスクロールバーのつまみと矢印が水色になり、レールが薄い水色になっている。下の「::-webkit-scrollbar(幅12px、丸いつまみ)」では、矢印がなく、薄い水色のレールの中に、両端の丸い水色のつまみが出ている
上から、何も指定しない箱、標準の2つのプロパティを指定した箱、::-webkit-scrollbar で作り込んだ箱。どれも Chromium 153 で撮影

色と太さを、標準の2つのプロパティで変える

スクロールする箱に、次の CSS を指定します。

css
.scroller {
  scrollbar-color: #00c8e8 #eefafd; /* つまみの色 レールの色 */
  scrollbar-width: thin;
}

MDN の scrollbar-color の説明にあるとおり、scrollbar-color には色を2つ書きます。1つ目はつまみ(スクロールに合わせて動く部分)の色、2つ目はレール(つまみが動く溝。MDN では「トラック」)の色です。

scrollbar-width に書ける値は auto、thin、none の3つで、px のような長さは書けません。

指定を1つずつ変えて、太さと色を測りました。色は、スクロールバーの幅の真ん中を、上から下まで1列読んだ画素の色です。

箱に指定したもの 太さ つまみの色 レールの色
何も指定しない 15px #8b8b8b #fcfcfc
scrollbar-color だけ 15px #00c8e8 #eefafd
scrollbar-width: thin だけ 10px #8b8b8b #fcfcfc
上の CSS(両方) 10px #00c8e8 #eefafd
scrollbar-width: none 0px ― ―

scrollbar-color は色だけを、scrollbar-width は太さだけを変えました。検証した Chromium のスクロールバーには、上下に三角の矢印のボタンがあり、この矢印もつまみと同じ色になりました。

scrollbar-width: none では、スクロールバーが消えて、太さは0pxになりました。MDN の scrollbar-width の説明には、スクロールバーを隠すとアクセシビリティを損なうので none は避けるように書かれています。thin や none にすると、ほかにスクロールする手段を用意していない場合に、スクロールしにくくなったり、できなくなったりするとも書かれています。

ページ全体のスクロールバーは、:root に指定する

ページ全体のスクロールバーの色を変えるときは、ルート要素(:root、つまり html 要素)に指定します。

css
:root {
  scrollbar-color: #00c8e8 #eefafd;
}

MDN の scrollbar-color の説明にあるとおり、ルート要素に指定した値は、ビューポート(ページ全体)のスクロールバーに使われます。高さ1200pxのページで試したところ、画面の右端に出た太さ15pxのスクロールバーは、つまみが #00c8e8、レールが #eefafd になりました。

scrollbar-color は子孫の要素に受け継がれます。:root に指定すると、ページの中のスクロールする箱でも、scrollbar-color の計算値が :root と同じ色になり、スクロールバーにその色が付きました。一方、scrollbar-width は受け継がれません。:root に scrollbar-width: thin を指定しても、中の箱の scrollbar-width は auto のままでした。この違いは、後の節で ::-webkit-scrollbar と組み合わせるときに関わってきます。

つまみを丸くするなら、::-webkit-scrollbar を使う

標準の2つのプロパティでは、つまみの形や、太さのpx単位の値は決められません。そこまで作り込むときは、::-webkit-scrollbar で始まる擬似要素を使います。

css
/* スクロールバー全体の太さ(縦のバーは width、横のバーは height) */
.scroller::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}

/* レール */
.scroller::-webkit-scrollbar-track {
  background: #eefafd;
}

/* つまみ。レールと同じ色の枠で、細く丸く見せる */
.scroller::-webkit-scrollbar-thumb {
  background: #00c8e8;
  border: 3px solid #eefafd;
  border-radius: 6px;
}

.scroller::-webkit-scrollbar-thumb:hover {
  background: #067a98;
}

MDN の ::-webkit-scrollbar の説明にあるとおり、::-webkit-scrollbar はスクロールバー全体、::-webkit-scrollbar-track はレール、::-webkit-scrollbar-thumb はつまみを指します。どれも標準の仕様にはない、ブラウザ独自の擬似要素です。

この CSS で、スクロールバーの太さは12pxになりました。つまみの幅は、12pxから左右の枠3pxずつを除いた6pxです。枠をレールと同じ色にしたので、レールの中に細いつまみが浮いているように見えます。つまみのいちばん上の行では、両端の画素がレールの色とつまみの色の中間の色でした。つまみの角が丸く描かれています。何も指定しない箱にあった上下の矢印は、出ませんでした。

:hover を付けた指定も効きました。つまみにマウスを乗せると、つまみの色は #00c8e8 から #067a98 に変わりました。

丸いつまみを下へ、次に上へドラッグし、箱の下のスクロール位置の数字が変わる様子。マウスを乗せている間は、つまみが濃い水色になる
::-webkit-scrollbar で作ったつまみを、マウスで下へ、次に上へドラッグする様子。マウスを乗せている間は、つまみの色が濃くなる

MDN の ::-webkit-scrollbar の説明には、スクロールバーの見た目を既定から変えると、ほかのサイトやアプリと見た目がそろわず、使いにくくなるので、避けるべきだと書かれています。変える場合は、色のコントラストを十分にとり、タッチで操作する部分の幅と高さを44px以上にするよう勧めています。この記事の例(太さ12px)は、この大きさには届いていません。

2つのやり方を混ぜると、::-webkit-scrollbar は無視される

上の ::-webkit-scrollbar の CSS に、標準のプロパティを足して測りました。

::-webkit-scrollbar の CSS に足した指定 太さ つまみ
何も足さない 12px 丸い水色(#00c8e8)
同じ箱に scrollbar-width: thin 10px 既定の灰色(#8b8b8b)
同じ箱に scrollbar-color: #d85878 #eefafd 15px ピンク(#d85878)
:root に scrollbar-color: #d85878 #eefafd 15px ピンク(#d85878)
:root に同じ指定、箱に scrollbar-color: auto 12px 丸い水色(#00c8e8)
:root に scrollbar-width: thin 12px 丸い水色(#00c8e8)

同じ箱に scrollbar-width: thin を足すと、::-webkit-scrollbar の指定は太さも色もまるごと効かなくなり、既定の細いスクロールバー(灰色のつまみ、#fcfcfc のレール、上下の矢印あり)になりました。scrollbar-color を足したときも、太さは既定の15pxで、色だけが scrollbar-color の色になりました。

:root に scrollbar-color を指定しただけでも、箱の ::-webkit-scrollbar は効かなくなりました。箱が scrollbar-color を受け継いだためです。箱に scrollbar-color: auto を指定すると、丸い水色のつまみに戻りました。:root の scrollbar-width: thin は箱に受け継がれないので、箱の ::-webkit-scrollbar はそのまま効きました。

ポイント

scrollbar-color か scrollbar-width の計算値が auto 以外になっている要素では、::-webkit-scrollbar の指定が使われません。

この動きは、英語版の MDN にある scrollbar-color の注記と scrollbar-width の注記のとおりです。

標準のプロパティが使えないブラウザ向けに、@supports で分ける

標準のプロパティを優先し、使えないブラウザでは ::-webkit-scrollbar を使うには、MDN の ::-webkit-scrollbar の説明にある書き方のように、@supports で分けます。次の CSS は、その書き方に、この記事の色と太さを当てはめたものです。

css
/* scrollbar-color が使えるブラウザ */
@supports (scrollbar-color: auto) {
  .scroller {
    scrollbar-color: #00c8e8 #eefafd;
    scrollbar-width: thin;
  }
}

/* ::-webkit-scrollbar が使えるブラウザ */
@supports selector(::-webkit-scrollbar) {
  .scroller::-webkit-scrollbar {
    width: 12px;
  }
  .scroller::-webkit-scrollbar-track {
    background: #eefafd;
  }
  .scroller::-webkit-scrollbar-thumb {
    background: #00c8e8;
    border: 3px solid #eefafd;
    border-radius: 6px;
  }
}

Chromium 153 では、CSS.supports() で調べると、2つの条件はどちらも true でした。両方のブロックが使われますが、前の節のとおり ::-webkit-scrollbar の指定は無視され、太さ10px、つまみ #00c8e8、レール #eefafd の、標準のプロパティだけを指定したときと同じスクロールバーになりました。

1つ目のブロックは、MDN の例と同じく、scrollbar-color に対応しているかどうかを条件にしています。この記事では、そのブロックに scrollbar-width も入れました。

対応しているブラウザ

MDN の互換性データ(@mdn/browser-compat-data 8.1.8)で調べました。

機能 Chrome Firefox Safari
scrollbar-color 121 64 26.2
scrollbar-width 121 64 18.2
::-webkit-scrollbar 2 なし(下の説明を参照) 4
::-webkit-scrollbar-thumb、::-webkit-scrollbar-track 2 なし 4
@supports selector() 83 69 14.1

互換性データによると、::-webkit-scrollbar は Firefox 153 で一部だけ使えるようになり、Firefox 155 で削除されています。注記によると、一部だけ対応していた間は、@supports selector(::-webkit-scrollbar) が true を返す一方、効くのは display: none と、0でない width か height だけでした。

​Posted by 86