テック技報最新号へ →
CSS

::scroll-marker と scroll-marker-group で、スクロールスナップのカルーセルに JS なしのタブを付ける

カルーセルに scroll-marker-group を指定すると、各スライドの ::scroll-marker がまとめてタブ列として描画され、クリックでそのスライドへスクロール・表示中のタブには :target-current が当たる。

@sanyampunia · 2026-10-21
#scroll-marker#カルーセル#タブ#scroll-snap#target-current#JS不要#新機能

どんな時に使う?

コード

html
<ul class="carousel">
  <li data-tab="概要">…</li>
  <li data-tab="仕様">…</li>
  <li data-tab="レビュー">…</li>
</ul>
css
.carousel {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* マーカーの並び(グループ)をスクロール領域の前に置く。tabs はタブリストとして扱わせる指定 */
  scroll-marker-group: before tabs;
}

.carousel > li {
  flex: 0 0 100%;
  scroll-snap-align: center;
}

/* マーカーが並ぶ入れ物。普通の flex コンテナとして見た目を作れる */
.carousel::scroll-marker-group {
  display: flex;
  gap: 8px;
  height: 48px;
}

/* スライドごとに1つ生成されるマーカー。ラベルは data 属性から取る */
.carousel > li::scroll-marker {
  content: attr(data-tab);
  padding-inline: 12px;
  border-radius: 999px;
}

/* いま表示中のスライドに対応するマーカー */
.carousel > li::scroll-marker:target-current {
  background: black;
  color: white;
}
  • マーカーをクリックすると対応するスライドまでスクロールし、スクロールやスワイプで表示中のスライドが変わると :target-current も自動で移る。現在地の管理を書く必要がない。
  • ラベルを出さずにドット表示にしたいなら、content: "" にして幅・高さ・丸みを付ければよい。
  • :target-current は目次のハイライトと同じ仕組み(:target-current で目次の「いま読んでいる項目」をCSSだけでハイライト)。目次ではリンクがマーカーになり、こちらでは疑似要素がマーカーになる。

注意点・対応状況

  • ::scroll-marker / ::scroll-marker-group / scroll-marker-group は Chromium 系の「CSS カルーセル」機能で、Firefox・Safari は未対応(2026-10 時点、Can I use で要確認)。未対応ブラウザではタブが出ないだけで、スクロールスナップのスライダーとしては動くので、プログレッシブエンハンスメント向き。
  • before tabs のような「位置+モード」の書き方は before / after だけの書き方より新しい。モード指定を解釈できないブラウザでは宣言ごと無視されるので、scroll-marker-group: before; を先に書いてから before tabs で上書きしておくと安全。
  • ラベルを attr() で疑似要素に入れる方式なので、翻訳ツールや一部の支援技術での読み上げはブラウザ実装に依存する。重要なラベルは実機のスクリーンリーダーで確認する。
  • 元の投稿はコードの要点のみ。HTML 構造・scroll-snap-align・ドット表示の案・フォールバックの書き方は補足として加えたもの。

出典

X の元の投稿を開く