ウェブサイトなどで、スクロールをすると特定のポイントに吸い付くように止まる動きを見かけることもあるかと思います。これをスクロールのスナップ機能と呼んだりするのですが、今回はCSSでスクロールのスナップ機能を実装してみたいと思います。以前はJavaScriptを用いて実装されていたことが多いと思いますので、イメージですと、とても複雑な処理や指定が必要になる感じがありますが、たった数箇所の指定だけで実現できてしまいます。それでは早速コードを見ていきます。
【HTML】※一部省略
<div class="container">
<section>
<span>1stコンテンツエリア</span>
</section>
<section>
<span>2ndコンテンツエリア</span>
</section>
<section>
<span>3rdコンテンツエリア</span>
</section>
<section>
<span>4thコンテンツエリア</span>
</section>
</div>
【CSS】
.container {
width: 100%;
height: 100vh;
scroll-snap-type: y mandatory;
overflow: auto;
}
section {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
scroll-snap-align: center;
}
section:nth-child(odd) {
background: #d0ff00;
}
section:nth-child(even) {
background: #52ffe5;
}
まずポイントになるのは親要素に指定している「scroll-snap-type」プロパティです。見慣れないプロパティですが、スクロールに対してのスナップを制御する重要な役割を果たします。値は主に下記の2つの内容を指定するといいでしょう。一つ目の値ではスクロール方向を、二つ目の値ではスナップの効力の強さを指定する形となります。
scroll-snap-typeプロパティの第一引数にはこのような値が入ります。
| x | 水平方向のスクロールでスナップ位置が対象となる |
|---|
| y | 垂直方向のスクロールでスナップ位置が対象となる |
|---|
| both | 水平方向と垂直方向の両方のスクロールでスナップ位置が対象となる |
|---|
scroll-snap-typeプロパティの第二引数にはこのような値が入ります。
| mandatory | 少しでもスナップ位置から外れている場合に、近い方のスナップ点にスナップされます、シビアなスナップの制約になります |
|---|
| proximity | スナップ位置から大きく離れている場合は、スナップされずにそのままの状態で止まり、緩やかなスナップの制約になります |
|---|
また、スナップ位置の対象となる子要素には「scroll-snap-align」プロパティを設定することで、スクロールのコンテナ要素においてどの位置でスナップさせるかを指定できます。「start」を指定するとコンテナ要素の開始位置に、「end」を指定するとコンテナ要素の終了位置に、「center」はコンテナ要素の中央にスナップ点が配置されます。
上記のコードで作成した
サンプルはこちらになります。動作を実際に確認してみてください。
スクロールスナップが効かない場合には
きちんと「scroll-snap-type」プロパティを指定しているにも関わらず、スクロールのスナップが確認できない時には次の2つのポイントを確認します。
・overflowプロパティでautoもしくはscrollが設定されている
・スクロールのコンテナ要素の高さが指定されている
つまり、スクロールのスナップを有効にするためには、コンテナ要素が正しくスクロールできる状態であるというのが前提になります。その上で、scroll-snap-typeプロパティでの指定が有効になります。
このように以前はJavaScriptを使った実装が行われていたものが、たった数個のCSSプロパティで実現できるのはとても便利ですよね。フルスクリーンのウェブサイトが増えてきている現在では、このプロパティを使うことでいろんなデザイン要件に対応できると思います。
(参考にさせていただいたサイト)
scroll-snap-type - CSS: カスケーディングスタイルシート | MDN