テック技報最新号へ →
CSS

scroll-snap で JS なしの「カード単位で止まる」横スクロールスライダー

横スクロールの親に scroll-snap-type: x mandatory、各カードに scroll-snap-align: start を付けるだけで、スワイプやトラックパッドでスクロールしたときにカードの端でピタッと止まる。

@KZpan_webdesign · 2026-10-20
#scroll-snap#スライダー#カルーセル#横スクロール#JS不要

どんな時に使う?

  • スマホで横スワイプするカード一覧・商品カルーセル・画像ギャラリーを、スライダー用ライブラリなしで作りたい時
  • 横スクロールの途中半端な位置で止まって、カードが見切れたままになるのを防ぎたい時

コード

html
<div class="slider">
  <div class="card">カード1</div>
  <div class="card">カード2</div>
  <div class="card">カード3</div>
</div>
css
.slider {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;   /* 横方向に必ず吸着させる */
  scroll-padding-inline: 16px;     /* 吸着位置を左端から 16px 内側にずらす */
  overscroll-behavior-x: contain;  /* 端まで行ってもページ側の戻る操作などに伝えない */
}

.card {
  flex: 0 0 80%;               /* 1枚を 80% 幅にして次のカードを少し覗かせる */
  scroll-snap-align: start;    /* カードの左端で止める(center にすると中央で止まる) */
}
  • scroll-snap-type はスクロールする親に、scroll-snap-align は止まらせたい子に付ける。2つ揃って初めて効く。
  • mandatory はスクロールが止まったら必ずどこかのカードに吸着、proximity は吸着点の近くで止まった時だけ吸着する。
  • 1回のスワイプで何枚も飛ばされたくない時は、カードに scroll-snap-stop: always を付けると1枚ずつ止まる。

注意点・対応状況

  • 主要ブラウザすべてで使える。
  • mandatory で、カードがスクロール領域より大きい(縦長の中身など)場合、中身の途中まで読めずに次の吸着点へ飛ばされることがある。そういう時は proximity にする。
  • キーボードでも操作できるよう、スクロール領域に tabindex="0" と aria-label を付けておくとよい。
  • 横スクロールのスクロールバーの出方を揃えたい場合は、テーブルの例だが 横スクロールするテーブルはラッパーで包む(table に overflow-x は効かない) も参考になる。
  • 元の投稿は scroll-snap-type と scroll-snap-align だけの最小例。scroll-padding-inline・overscroll-behavior-x・scroll-snap-stop は補足として加えたもの。

出典

X の元の投稿を開く