スクロールスナップを理解し使いこなす:サンプルコード集


スクロールスナップの仕組み

従来のスクロールでは、コンテンツは滑らかに動き、ユーザーは任意の位置で停止できました。一方、スクロールスナップ では、コンテンツを特定の領域(スナップポイント)に自動的に吸着させる機能が追加されます。まるで磁石のように、コンテンツがスナップポイントにピタッと収まるイメージです。

scroll-snap-align の役割

scroll-snap-align は、スナップポイントにおけるコンテンツの整列位置を決定します。具体的には、以下の2つの軸方向における整列を制御できます。

  • インライン軸方向
    横方向のスクロールの場合、要素の左端、中央、右端などを指定できます。
  • ブロック軸方向
    縦方向のスクロールの場合、要素の開始位置、中央、終了位置などを指定できます。

scroll-snap-align の構文

scroll-snap-align プロパティは、以下の値をカンマ区切りで2つ指定します。

  • 2つ目の値
    インライン軸方向における整列位置
  • 1つ目の値
    ブロック軸方向における整列位置

それぞれの方向に以下のいずれかの値を指定できます。

  • align-items
    要素の align-items プロパティの値に準拠
  • nearest
    スクロール方向に最も近い整列位置に整列
  • end
    要素の終了位置に整列
  • center
    要素の中央に整列
  • start
    要素の開始位置に整列


.container {
  scroll-snap-type: mandatory; /* スナップを強制 */
  scroll-snap-align: center start; /* 中央揃えかつ左揃え */
}

この例では、.container 要素は常に中央揃えかつ左揃えにスナップされます。

スクロールスナップ動作の調整

scroll-snap-type プロパティと併用することで、スクロールスナップの動作をさらに調整できます。scroll-snap-type の主な値は以下の通りです。

  • proximity
    スナップポイントに近い場合のみスナップ
  • mandatory
    スナップを強制(常にスナップポイントに留まる)
  • none
    スナップを無効化


.container {
  scroll-snap-type: proximity; /* スナップポイントに近い場合のみスナップ */
  scroll-snap-align: center start;
}

この例では、.container 要素は、スクロール位置がスナップポイントに十分近づいた場合のみ中央揃えかつ左揃えにスナップされます。

実用的な例

例1:セクションをページング

この例では、scroll-snap を使用して、セクションをページングのように表示します。

<div class="container">
  <section class="page">...</section>
  <section class="page">...</section>
  <section class="page">...</section>
</div>
.container {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  scroll-snap-type: mandatory;
  scroll-snap-align: start;
}

.page {
  flex: 1; /* 各セクションが同じ高さを占めるように設定 */
}

例2:横方向にスナップするギャラリー

この例では、scroll-snap を使用して、画像を横方向にスナップするギャラリーを作成します。

<div class="container">
  <img src="image1.jpg" class="item">
  <img src="image2.jpg" class="item">
  <img src="image3.jpg" class="item">
</div>
.container {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: mandatory;
  scroll-snap-align: start center;
}

.item {
  flex: 0 0 50%; /* 各画像が幅50%になるように設定 */
  margin: 0 10px; /* 画像


基本的な例

この例は、scroll-snap-align を使ってセクションを垂直方向にスナップする方法を示しています。

<div class="container">
  <section class="page">セクション 1</section>
  <section class="page">セクション 2</section>
  <section class="page">セクション 3</section>
</div>
.container {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  scroll-snap-type: mandatory;
  scroll-snap-align: center start;
}

.page {
  flex: 1;
  text-align: center;
  padding: 20px;
  border: 1px solid #ccc;
  margin-bottom: 10px;
}

説明

  • .pagepadding: 20px; border: 1px solid #ccc; margin-bottom: 10px; を設定することで、セクションに余白とボーダーを追加します。
  • .pagetext-align: center; を設定することで、セクション内のテキストを中央揃えにします。
  • .pageflex: 1; を設定することで、各セクションが均等な高さを占めるようにします。
  • .containerscroll-snap-align: center start; を設定することで、セクションを中央揃えかつ左揃えにスナップします。
  • .containerscroll-snap-type: mandatory; を設定することで、スクロールをスナップポイントに強制的に吸着させます。
  • .containeroverflow-y: auto; を設定することで、垂直方向のスクロールバーを表示します。
  • .containerdisplay: flex; flex-direction: column; を設定することで、セクションを縦方向に並べます。

実行結果

このコードを実行すると、ブラウザウィンドウよりも背の高い3つのセクションが表示されます。ユーザーは、セクション間を上下にスクロールし、各セクションが中央揃えかつ左揃えにスナップされる様子を確認できます。

横方向スナップ

この例は、scroll-snap-align を使って画像を横方向にスナップする方法を示しています。

<div class="container">
  <img src="image1.jpg" class="item">
  <img src="image2.jpg" class="item">
  <img src="image3.jpg" class="item">
</div>
.container {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: mandatory;
  scroll-snap-align: start center;
}

.item {
  flex: 0 0 50%; /* 各画像が幅50%になるように設定 */
  margin: 0 10px;
  border: 1px solid #ccc;
}

説明

  • .itemmargin: 0 10px; border: 1px solid #ccc; を設定することで、画像に余白とボーダーを追加します。
  • .itemflex: 0 0 50%; を設定することで、各画像が幅50%になるようにします。
  • .containerscroll-snap-align: start center; を設定することで、画像を左揃えかつ中央揃えにスナップします。
  • .containerscroll-snap-type: mandatory; を設定することで、スクロールをスナップポイントに強制的に吸着させます。
  • .containeroverflow-x: auto; を設定することで、横方向のスクロールバーを表示します。
  • .containerdisplay: flex; を設定することで、画像を横方向に並べます。

実行結果

このコードを実行すると、ブラウザウィンドウよりも幅の広い3つの画像が表示されます。ユーザーは、画像間を左右にスクロールし、各画像が左揃えかつ中央揃えにスナップされる様子を確認できます。



JavaScript によるプログラム制御

  • イベントリスナーとスクロール制御
    JavaScript でイベントリスナーを使用してスクロールイベントを検出し、それに応じて要素をプログラムでスナップさせることもできます。この方法は柔軟性がありますが、scroll-snap-align よりも複雑でコード量が多くなります。
  • ライブラリ使用
    Smooth Scrolling Libraryなどのライブラリを使用することで、JavaScriptでスナップ機能を再現できます。これらのライブラリは、scroll-snap-align の互換性や、より高度なアニメーション機能を提供する場合があります。

場合によっては、scroll-snap-align の代替として以下のCSSプロパティが役立ちます。

  • transform: translateX/Y
    JavaScriptを使用して、要素をプログラムで移動させ、スナップ効果をシミュレートすることができます。高度なアニメーションや動的なレイアウトに適しています。
  • position: sticky
    要素を画面内に固定し、スクロールしても常に表示させることができます。ナビゲーションバーなどに適しています。

最適な代替方法の選択

最適な代替方法は、要件や状況によって異なります。

  • 特定のユースケース に適した代替方法もあります。例えば、ナビゲーションバーには position: sticky 、アニメーションには transform が適しています。
  • より高度な機能や柔軟性が必要な場合は、JavaScriptによるプログラム制御 を検討してください。
  • **シンプルでクロスブラウザ互換性に優れた方法が必要な場合は、scroll-snap-align がおすすめです。