CSSのscroll-snapで作るカルーセルスライダー|JavaScript不要
JavaScriptを使わなくても、CSSの scroll-snap を使えば、スマートフォンでよく見かけるカルーセルスライダーや画像スライダーを簡単に実装できます。
Swiperなどのライブラリを導入するほどではないケースや、軽量な実装をしたい場合にもおすすめです。
CSSのscroll-snapとは?
CSSの scroll-snap は、スクロールを停止したときに、指定した位置へ自動的に吸着(スナップ)させるCSS機能です。
スマートフォンのカルーセルや、画像スライダー、全画面スクロールなどによく利用されています。
JavaScriptを書かなくても自然なスライド操作を実現できるため、シンプルで軽量なUIを作りたい場合に便利です。
基本のカルーセル
CodePenデモ
See the Pen 基本のカルーセル|JavaScript不要のカルーセルスライダー|scroll-snap by mkl may (@mkl-may) on CodePen.
HTML構造
スライド全体を囲む親要素(スクロールコンテナ)と、各スライドとなる子要素を用意します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<div class="carousel"> <div class="carousel_item"> <div class="card"><a href="/">Slide 1</a></div> </div> <div class="carousel_item"> <div class="card"><a href="/">Slide 2</a></div> </div> <div class="carousel_item"> <div class="card"><a href="/">Slide 3</a></div> </div> <div class="carousel_item"> <div class="card"><a href="/">Slide 4</a></div> </div> <div class="carousel_item"> <div class="card"><a href="/">Slide 5</a></div> </div> </div> |
CSS設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
.carousel { display: flex; /* カードを横並びにする */ gap: 20px; /* カード同士の間隔 */ overflow-x: auto; /* 横スクロールを有効にする */ scroll-snap-type: x mandatory; /* 横方向に必ずスナップさせる */ scroll-behavior: smooth; -webkit-overflow-scrolling: touch; } .carousel_item { flex: 0 0 85%; /* カード幅をコンテナの85%にする */ scroll-snap-align: center; /* カードを中央位置にスナップさせる */ } |
親要素には overflow-x: auto を指定して横スクロールを有効にします。
さらに scroll-snap-type: x mandatory を指定すると、スクロール終了時にカードが自動的にスナップします。
子要素には scroll-snap-align を指定し、どの位置で停止するかを決めます。
主なプロパティ
| プロパティ | 役割 |
|---|---|
| scroll-snap-type | スナップ方向・動作を指定 |
| scroll-snap-align | 停止位置を指定 |
| gap | カード同士の余白 |
| flex | カードの幅(flex-basis)を指定 |
1画面表示のカルーセル
スライドを画面いっぱいに表示したい場合は、スライド幅を100%に設定します。
.carousel_item {
flex: 0 0 100%;
}
CodePenデモ
See the Pen 1画面表示|JavaScript不要のカルーセルスライダー|scroll-snap by mkl may (@mkl-may) on CodePen.
画像スライダーやヒーロービジュアルなど、一度に1枚だけ見せたいケースに適しています。
レスポンシブ対応のカルーセル
画面幅に応じてカードの表示枚数を変更することで、スマートフォン・タブレット・PCそれぞれに最適なレイアウトを実現できます。
例えば、スマートフォンでは1枚、タブレットでは2枚、PCでは3枚表示するといったレイアウトも、各スライドの幅(flex-basis)をメディアクエリで切り替えるだけで実装できます。
CodePenデモ
See the Pen 画面幅に応じて表示切り替え(レスポンシブ)|JavaScript不要のカルーセルスライダー|scroll-snap by mkl may (@mkl-may) on CodePen.
CSS設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
.carousel .carousel_item { flex: 0 0 calc(100% - 40px); } /* --- Tablet --- */ @media (min-width: 768px) { .carousel .carousel_item { flex: 0 0 calc(50% - 10px); } } /* --- PC --- */ @media (min-width: 1024px) { .carousel .carousel_item { flex: 0 0 calc((100% - 40px) / 3); } } |
全画面スクロール
scroll-snapは横スクロールだけでなく、縦方向にも利用できます。
CodePenデモ
See the Pen 全画面スクロール|JavaScript不要のカルーセルスライダー|scroll-snap by mkl may (@mkl-may) on CodePen.
HTML構造
|
1 2 3 4 5 |
<div class="carousel-hero"> <div class="hero hero01">HERO 1</div> <div class="hero hero02">HERO 2</div> <div class="hero hero03">HERO 3</div> </div> |
CSS設定
|
1 2 3 4 5 6 7 8 9 10 |
.carousel-hero { height: 100vh; overflow-y: auto; scroll-snap-type: y mandatory; } .hero { height: 100vh; scroll-snap-align: start; } |
親要素に scroll-snap-type: y mandatory;、各セクションに scroll-snap-align: start; を指定すると、1画面ごとに切り替わるレイアウトを実装できます。
スクロールバーを非表示にする
カルーセルではスクロールバーを表示したくないケースもあります。
CodePenデモ
See the Pen スクロールバー非表示|JavaScript不要のカルーセルスライダー|scroll-snap by mkl may (@mkl-may) on CodePen.
CSS設定
|
1 2 3 4 5 6 7 |
.carousel { scrollbar-width: none; } .carousel::-webkit-scrollbar { display: none; } |
Firefoxでは scrollbar-width: none;、Chromium系ブラウザでは ::-webkit-scrollbar を利用することで非表示にできます。
ただし、スクロールバーを隠すと横スクロールできることが伝わりにくくなるため、次のカードを少し見切れさせるデザインがおすすめです。
また、PCでは Shiftキーを押しながらマウスホイールを操作すると横スクロールできるブラウザが多いですが、マウスやOSによって挙動は異なります。
タッチパッドの横スクロールや横スクロール対応マウスでも操作できます。
なお、スクロールバーを非表示にすると、キーボードやスクリーンリーダー利用者にとって操作性が分かりにくくなる場合があります。
ドットナビゲーション
Scroll Marker は、CSSだけでカルーセルのドットナビゲーションを生成できる新しい仕様です。
JavaScriptを使わずに、現在表示中のスライドを示すドットナビゲーションを表示できます。
ただし、執筆時点では対応ブラウザが限られているため、利用する際はブラウザ対応状況を確認しましょう。
CodePenデモ
See the Pen Scroll Marker|JavaScript不要のカルーセルスライダー|scroll-snap by mkl may (@mkl-may) on CodePen.
CSS設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
.carousel { scroll-marker-group: after; } .carousel::scroll-marker-group { display: flex; justify-content: center; gap: 12px; margin-top: 20px; } .carousel > .carousel_item::scroll-marker { content: ""; width: 12px; height: 12px; border: 2px solid #999; border-radius: 50%; background: transparent; } .carousel > .carousel_item::scroll-marker:target-current { background: #333; border-color: #333; } |
Scroll Button(前後ボタン)
Scroll Button は、CSSだけでカルーセルの前後ボタンを生成できる新しい仕様です。
従来はJavaScriptで実装することが一般的でしたが、対応ブラウザではCSSのみでシンプルに実装できます。
こちらも比較的新しい機能のため、ブラウザ対応状況を確認したうえで採用すると安心です。
CodePenデモ
See the Pen Scroll Button(前後ボタン)|JavaScript不要のカルーセルスライダー|scroll-snap by mkl may (@mkl-may) on CodePen.
※ ::scroll-button() は実装が進行中のCSS機能です。
ブラウザの実装状況や実行環境(CodePenなど)によって、ボタンの表示位置や挙動がわずかに異なる場合があります。
CSS設定
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
.carousel { position: relative; } .carousel::scroll-button(*) { position: absolute; top: 50%; display: flex; justify-content: center; align-items: center; width: 44px; height: 44px; border: none; border-radius: 999px; background: rgba(255, 255, 255, .95); box-shadow: 0 2px 10px rgb(0 0 0 / .15); font-size: 20px; } .carousel::scroll-button(left) { content: "←"; } .carousel::scroll-button(right) { content: "→"; } .carousel::scroll-button(*):disabled { opacity: .35; } |
scroll-snapでよく使うCSS一覧
| プロパティ | 役割 |
|---|---|
| scroll-snap-type | スナップ方向・動作を指定 |
| scroll-snap-align | 停止位置を指定 |
| overflow-x | 横スクロールを有効化 |
| overflow-y | 縦スクロールを有効化 |
| scroll-behavior | スムーズスクロール |
| scrollbar-width | スクロールバーの表示切替 |
| scroll-marker-group | ドットナビゲーション(新仕様) |
| ::scroll-marker | ドットのデザイン |
| ::scroll-button | 前後ボタン(新仕様) |
まとめ
CSSの scroll-snap を利用すると、JavaScriptなしでもスムーズなカルーセルや全画面スクロールを実装できます。
今回紹介した内容を組み合わせることで、次のようなUIをCSSだけで実装できます。
- 基本のカルーセル
- 1画面表示スライダー
- レスポンシブ対応カルーセル
- 全画面スクロール
- スクロールバーの非表示
- Scroll Marker(ドットナビゲーション)
- Scroll Button(前後ボタン)
軽量で保守性の高い実装をしたい場合は、まずはCSSだけで実現できるかを検討してみるとよいでしょう。