2026年4月16日
CSS scroll-snap とは?なぜ使うの?
「スクロールすると次のセクションにぴったり止まる」——そんなオシャレな動きを見たことはありませんか?あれが CSS scroll-snap(スクロールスナップ) です。
たとえば、スマホのInstagramのリール画面や、Webサイトのフルページスクロール。スクロールするとコンテンツがページ全体に「ぱちっ」と合わさります。
これを実現するには昔はJavaScriptが必要でしたが、今はCSSだけで実装できます。コードも短くてシンプルです。
💡 こんな場面で使われます
- 横スクロールの画像スライダー(カルーセル)
- 縦方向のフルページスクロール(1ページずつ切り替わる)
- スマホの商品画像切り替え
CSSの基本がまだ不安な人は「CSSとは?初心者向けにわかりやすく解説」を先に読んでおきましょう。
基本的な使い方
scroll-snapは「親要素」と「子要素」に分けてプロパティを指定します。
- 親要素:
scroll-snap-type(スクロール方向とスナップの強さ) - 子要素:
scroll-snap-align(どこでスナップするか)
/* 親要素:スクロール方向とスナップの強さを指定 */
.container {
overflow-y: scroll;
scroll-snap-type: y mandatory; /* 縦方向・強制スナップ */
height: 100vh; /* 画面の高さに合わせる */
}
/* 子要素:スナップする位置を指定 */
.section {
scroll-snap-align: start; /* 上端でスナップ */
height: 100vh; /* 1セクションが画面全体 */
} たったこれだけで、縦方向のフルページスクロールが完成します。height: 100vh は「画面の高さ(100%)」を意味します。
👉 displayプロパティ完全解説も参考にしてください。
横スクロールスライダーを作ろう
スマホでよく見る「横にスワイプして次の画像が見られるスライダー」も scroll-snap で作れます。
/* 親要素 */
.slider {
display: flex; /* 子要素を横並びにする */
overflow-x: scroll; /* 横スクロールを有効にする */
scroll-snap-type: x mandatory; /* 横方向・強制スナップ */
gap: 16px;
/* スクロールバーを非表示にする(任意) */
scrollbar-width: none;
}
/* 子要素(各スライド) */
.slide {
scroll-snap-align: start; /* 左端でスナップ */
flex-shrink: 0; /* 縮まないようにする */
width: 100%; /* 1スライドが横幅全体 */
height: 300px;
background-color: #0d9488;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24px;
font-weight: bold;
} <div class="slider">
<div class="slide">スライド 1</div>
<div class="slide">スライド 2</div>
<div class="slide">スライド 3</div>
</div> ⚠️ flex-shrink: 0 を忘れずに!
スライドがぺしゃんこに縮んでしまうときは flex-shrink: 0; を指定してください。flexboxのデフォルトで要素が縮もうとするため、これを防ぐ必要があります。
▶ プレビュー
🔥 CSSセレクターの使い方で実践してみましょう。
scroll-snap-typeの値一覧
scroll-snap-type は「方向」と「強さ」を組み合わせて指定します。
| 値 | 意味 |
|---|---|
x mandatory | 横方向・必ずスナップ |
y mandatory | 縦方向・必ずスナップ |
x proximity | 横方向・近くにあればスナップ |
y proximity | 縦方向・近くにあればスナップ |
both mandatory | 縦横両方向・必ずスナップ |
mandatory(マンデートリー) は「強制」という意味です。スクロールを止めると、必ず一番近いスナップ位置に移動します。
proximity(プロキシミティ) は「近さ」という意味です。スナップ位置に十分近いときだけスナップします。途中で止まることもできます。
💡 hoverで動きをつける方法で基礎を確認できます。
scroll-snap-alignの値一覧
scroll-snap-align は子要素のどの位置でスナップするかを指定します。
| 値 | 意味 |
|---|---|
start | 要素の先頭(上端または左端)でスナップ |
center | 要素の中央でスナップ |
end | 要素の末尾(下端または右端)でスナップ |
フルページスクロールなら start、中央に小さいカードを表示するなら center がよく使われます。
scroll-paddingで余白を調整する
ヘッダーが固定表示(sticky/fixed)になっている場合、スナップ位置がヘッダーに隠れてしまうことがあります。scroll-padding でオフセット(ずらし量)を設定できます。
.container {
scroll-snap-type: y mandatory;
scroll-padding-top: 80px; /* ヘッダーの高さ分だけずらす */
overflow-y: scroll;
height: 100vh;
} これで、ヘッダー(高さ80px)がある場合でも、コンテンツがヘッダーの下からきれいに表示されます。
フルページスクロールの実装例
ランディングページ(LP)でよく使われる、1ページずつ縦にスクロールするレイアウトを作ってみましょう。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>フルページスクロール練習</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
/* スクロールコンテナ */
.page-wrapper {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
/* 各セクション */
.section {
height: 100vh;
scroll-snap-align: start;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
font-weight: bold;
color: white;
}
.section:nth-child(1) { background-color: #0d9488; }
.section:nth-child(2) { background-color: #2563eb; }
.section:nth-child(3) { background-color: #7c3aed; }
.section:nth-child(4) { background-color: #dc2626; }
</style>
</head>
<body>
<div class="page-wrapper">
<section class="section">セクション 1</section>
<section class="section">セクション 2</section>
<section class="section">セクション 3</section>
<section class="section">セクション 4</section>
</div>
</body>
</html> このコードをコピーしてHTMLファイルに貼り付けて、ブラウザで確認してみましょう。スクロールするとセクションごとにぴったり止まります。
よくある失敗と対策
失敗1:スナップが効かない
親要素に overflow: scroll または overflow: auto を指定していないとスナップが効きません。また、子要素に明確な高さ(または幅)を指定しないと意図通りに動かないことがあります。
失敗2:コンテンツが途中で切れる
scroll-snap-type: y mandatory の場合、スクロールは必ずスナップ位置に止まります。コンテンツが1画面より長い場合、はみ出た部分が見えなくなります。そういう場合は proximity を使うか、コンテンツを分割しましょう。
失敗3:スマホでガクガクする
iOSでスムーズなスクロールを実現するには、スクロールコンテナに -webkit-overflow-scrolling: touch; を追加すると改善されることがあります。
scroll-behaviorとの組み合わせ
scroll-behavior: smooth; をスクロールコンテナに追加すると、スナップする際のアニメーションが滑らかになります。
.container {
scroll-snap-type: y mandatory;
scroll-behavior: smooth; /* スムーズにスナップ */
overflow-y: scroll;
height: 100vh;
} まとめ
- ✅ 親要素に
scroll-snap-type、子要素にscroll-snap-alignを指定する - ✅
mandatory:必ずスナップ、proximity:近くにあればスナップ - ✅
scroll-snap-align: startが最もよく使われる(先頭でスナップ) - ✅ 横スクロールスライダーも縦フルページスクロールも作れる
- ✅
scroll-paddingで固定ヘッダーとの干渉を調整できる - ✅ JavaScriptなしでCSSだけで実装できる
scroll-snapを使いこなすと、インタラクティブなレイアウトが作れます。CSSのレッスンでさらに詳しく学んでみましょう。
あわせて読みたい記事
- CSSとは?初心者向けに解説 — CSS基礎に戻る
- CSSフレックスボックス入門 — flexboxで横並びレイアウト
- CSSアニメーション入門 — スクロールに動きを追加
- レスポンシブデザイン入門 — スマホ対応の実装