CSSのscroll-snapでスクロールを制御する方法

CSS scroll-snapの使い方を初心者向けに解説。snap-type・snap-align・scroll-paddingの指定から横スクロールやフルページスクロールの実装までコード例で紹介。中高生向け。無料。

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コースでは、scroll-snapを含む実践的なデザインをブラウザだけで学べます。無料・登録不要です。

CSSコースを見る →
目次

コースで実際に手を動かして学ぼう

レッスンではコードを書きながら基礎が身につきます

HTMLコースを始める →

この記事に出てくる用語

📣 この記事が役に立ったら

Xでシェア

💬 引用する場合はこちらをご利用ください:

CSS scroll-snapの使い方を初心者向けに解説。snap-type・snap-align・scroll-paddingの指定から横スクロールやフルページスクロールの実装までコード例で紹介。中高生向け。無料。

出典: https://start-web-programming.com/blog/css-scroll-snap/