テック技報最新号へ →
CSS

::scroll-button() でカルーセルの前へ・次へボタンを JS なしで付ける

スクロールするコンテナに ::scroll-button(left) / ::scroll-button(right) を書くと、ブラウザが本物のボタンを生成し、押すと1画面ぶんスクロールしてくれる。

@clockmaker · 2026-10-25

::scroll-marker と scroll-marker-group で、スクロールスナップのカルーセルに JS なしのタブを付ける がインジケーター(ドット・タブ)側の話なら、こちらは矢印ボタン側。組み合わせると Swiper などのライブラリなしで一通りのカルーセルになる。

どんな時に使う?

  • 画像スライダーやカード一覧に「◀ ▶」ボタンを付けたいが、JS ライブラリを入れたくない時
  • ボタンのキーボード操作や読み上げを自前で作り込みたくない時(ブラウザが button の役割を自動で付ける)

コード

html
<div class="container">
  <ul class="carousel">
    <li class="item"><img src="01.jpg" alt=""></li>
    <li class="item"><img src="02.jpg" alt=""></li>
    <!-- … -->
  </ul>
</div>
css
.container {
  display: grid;
  /* 上段にスライド、下段に「左ボタン・ドット・右ボタン」 */
  grid-template-areas: "item item item" "left markers right";
}

.carousel {
  grid-area: item;
  display: grid;
  grid-auto-flow: column;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-snap-stop: always;   /* 速く押しても1枚ずつ止まる */
  scroll-behavior: smooth;
  scrollbar-width: none;
  scroll-marker-group: after; /* ドットも付けるなら */
}

/* 両方のボタン共通 */
.carousel::scroll-button(*) {
  inline-size: 48px;
  block-size: 48px;
  border-radius: 50%;
}

/* content の「/」の後ろが読み上げ用のテキスト */
.carousel::scroll-button(left) {
  content: "◀" / "前へ";
  grid-area: left;
  justify-self: end;
}
.carousel::scroll-button(right) {
  content: "▶" / "次へ";
  grid-area: right;
}

/* 端まで来るとボタンは自動で無効になる */
.carousel::scroll-button(*):disabled {
  opacity: .3;
}
  • 括弧の中は *(両方)、left / right。縦スクロールなら up / down、書字方向に合わせるなら inline-start / inline-end なども使える。
  • content: "◀" / "前へ" の / の後ろは代替テキスト。記号だけのボタンでもスクリーンリーダーで「前へ」と読まれる。
  • 生成されたボタンはスクロールコンテナの兄弟のように扱われるので、親の grid で grid-area を使って配置できる。
  • ボタンをスライドの上に重ねたい時は、コンテナに anchor-name、ボタンに position: absolute; position-anchor: …; top: anchor(center); を付けてアンカー配置する(ガイド: アンカー配置(CSS Anchor Positioning) 参照)。

注意点・対応状況

  • ::scroll-button() は Chrome・Edge 135 以降。記事作成時点で Firefox・Safari は未対応なので、未対応環境ではボタンが出ず、普通の横スクロール(スワイプ・スクロールバー)になるだけ、という前提で使う。
  • 最後のスライドで「次へ」を押したら先頭に戻る、といったループはまだできない。
  • ::scroll-button() はスクロールできる要素にしか効かない(overflow が visible だと何も出ない)。

出典

X の元の投稿を開く