on:2018年9月14日sponsorsCSSのscroll-snapプロパティを使用すると、スマホのホーム画面のようにちょっとずらすだけで、すぐに次のコンテンツを表示させることができます。今まではJavaScriptの領域でしたが、これからはCSSのみで実装できます。scroll-snapプロパティの基礎知識と便利な使い方を紹介します。Snapping下記は各ポイントを意訳したものです。※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。「scroll-snapプロパティ」の便利な使い方スクロールスナップのユーザーエクスペリエンス最後にスクロールにスナップさせる「scroll-snapプロパティ」CSSのscroll-snapプロパティを使用すると、ユーザーがスクロールを終了した後にビューポートを特定の要素または場所にスナップさせることができます。スナップさせるとは、期待した位置にぴたっと表示させることで、スクリーンいっぱいのコンテンツが並んだページのインタラクションを構築するのに最適です。下記はスマホのホーム画面をイメージした水平スクロールのコンテンツです。垂直の縦長ページにも利用できます。CodePen.スマホでもscroll-snapは、動作します。「scroll-snapプロパティ」のサポートブラウザscroll-snapのサポートブラウザは、Chrome、Firefox、Edge、IE、Safariのデスクトップ用ブラウザのすべてでサポートされています。モバイル用のブラウザでは、iOS用のSafaiのみサポートされています。scroll-snapは2016年に導入されて以来、大幅に改善されています。Pointsscroll-snapのサポートブラウザ「scroll-snapプロパティ」の基礎知識scroll-snapは、コンテナの親要素にscroll-snap-typeプロパティを、その内側の子要素にscroll-snap-alignプロパティを定義するのが基本的な使い方です。これだけで、親要素がスクロールされると、定義した子要素にスナップされます。コードを見てましょう。class='child'></section>...</div>親要素と子要素にscroll-snapを定義します。start;}ちなみに、仕様の最初のバージョンでは、下記のようにrepeatを使用して手動でスナップポイントを設定していました。repeat(300px);}最初のバージョンの方法は、使うシーンがかなり限定されてしまいます。上記の指定だと、300pxの均等に配置されたスナップポイントのみを使用できるため、異なるサイズの要素にスナップさせることはできません。スクリーンサイズによって異なる要素にも使用できません。2018年9月現在、Firefox、Edge、IEはこの最初のバージョンの仕様をサポートしていますが、ChromeとSafariは要素ベースの新しい方法をサポートしています。両方の指定方法を一緒に使用すると(同サイズの要素にスナップさせる場合)、両タイプのブラウザをサポートできます。start;}scroll-snapを使用する際の最適な記述方法は、要素ベースの構文を排他的に使用し、要素ベースをサポートしていないブラウザをサポートするためにポリフィルを使用することです。この記事で紹介しているデモはこの方法で実装しています。css-scroll-snap-polyfill残念なことに、このポリフィルはビルドプロセスを使用していない場合は少し使いにくいです。簡単な方法は、bundle.runのスクリプトにリンクし、DOMがロードされたらcssScrollSnapPolyfill()を使用して初期化することです。このポリフィルでは要素ベースをサポートします、初期のrepeatベースはサポートしていません。親要素の「scroll-snapプロパティ」scroll-snapプロパティは親要素と子要素の両方に適用され、それぞれに固有の値が設定されます。FlexboxのFlexコンテナとFlexアイテムと同じような感じです。scroll-snapの場合、親要素はSnapコンテナになります。親要素に使用するプロパティと値を見てましょう。「mandatory」は、ユーザーがスクロールを停止するたびにブラウザがスナップポイントにスナップされます。「proximity」はそれほど厳密ではなく、適切であればスナップポイントにスナップされます。実際に動作を試してみると、スナップポイントの数100ピクセル以内でスクロールを停止すると、スナップされることが分かります。CodePen.より一貫したユーザーエクスペリエンスが必要であることは分かりますが、仕様が指摘しているように、危険でもあります。スクロールするコンテナ内の子要素がビューポートよりも大きい場合を想像してみてください。mandatory」の場合、要素の上端または下端のいずれかに常にスナップされてしまい、背が高い要素の中間部分はスクロールできなくなります。scroll-paddingデフォルトでは、コンテンツはコンテナの端にスナップされます。これは、「scroll-padding」で変更できます。「scroll-padding」は通常のpaddingと同じ構文です。固定ヘッダのレイアウトなど、コンテンツの途中に入る要素がある場合に便利です。続いて、子要素に使用するscroll-snapプロパティを見てましょう。scroll-snap-alignscroll-snap-alignは、要素のどの部分がコンテナにスナップするかを指定できます。end」の3つがあります。end」の3つの値は、スクロール方向に関連しています。垂直方向にスクロールする場合は、startは要素の上端を指します。水平方向にスクロールする場合は、左端です。centerとendも同じ仕様です。使用する時は、スクロール方向ごとに異なる値をスペースで区切って設定できます。「normal」と「always」scroll-snap-stopはデフォルトでは、ユーザーがスクロールを停止した時に開始されます。停止する前にいくつかのスナップポイントをスキップできます。always」を設定します。この記述により、ユーザーがスクロールを続ける前にスクロールコンテナが強制的にその要素で停止します。2018年9月現在、ブラウザはscroll-snap-stopをネイティブにサポートしていません。「scroll-snapプロパティ」の便利な使い方scroll-snapを使用したデモを見てましょう。垂直方向のリスト垂直方向の各リスト要素にスナップさせるために必要なCSSは、たった2つです。親要素のコンテナに、縦のy軸に沿ってスナップするように定義します。mandatory;}あとは、スナップポイントを定義するだけです。各リスト要素の上部にスナップさせるように定義します。start;}たったこれだけのCSSで、完了です。水平方向のスライダーを作成するためには、コンテナに横のx軸に沿ってスナップされるように定義します。scroll-paddingを使用して、子要素がコンテナの中央にスナップされるようにします。50%;}あとは、どのポイントにスナップするかをコンテナに伝えるだけです。ギャラリーを中心にするために、各要素の中心点をスナップポイントとして定義します。center;}水平方向のスライダーも簡単に作成できます。CodePen.垂直方向のフルスクリーンコンテンツ縦長ページでよく見かけるレイアウトも非常に簡単です。スナップポイントは、直接<body>要素に定義することができます。mandatory;}あとは、各セクションをビューポートのサイズいっぱいにし、上端をスナップポイントとして定義するだけです。start;}非常にシンプルなCSSで、縦長ページも実装できます。CodePen.水平方向のフルスクリーンコンテンツ水平方向にすると、どうなるでしょう?これも簡単です。コンセプトは垂直方向と同じで、<body>要素の定義をx軸に変えるだけです。start;}横方向のレイアウトも簡単です。CodePen.2Dのグリッドscroll-snapは、同時に2つの方向で機能します。ここでも、<body>要素に直接scroll-snap-typeを定義します。2方向なので、値は「both」です。mandatory;}あとは、各タイルの左上隅をスナップポイントとして定義します。start;}画像などのギャラリーでよく使用されるレイアウトです。CodePen.スクロールスナップのユーザーエクスペリエンススクロールを扱うのは、危険なビジネスです。スクロールはユーザーがWebとやり取りするための基本的な操作であるため、何らかの方法で変更してしまうと、スクロールジャック(Scrolljacking)という言葉があるように不快感を与えることがあります。ここで紹介した「scroll-snap」の素晴らしい点は、スクロールの位置を制御するものではないということです。ユーザーがスクロールした際にスナップする位置のリストを与えるだけです。提供するインターフェースはどのプラットフォームであっても、ネイティブのインターフェース(同じアニメーションなどを使用する)のように感じることになります。「scroll-snap」は特に、スマホでうまく機能するのも大きな利点です。スマホでは、このスクロールのスナップがUIの一部で採用されています。iOSとAndroidのホーム画面は、スナップポイント付きの水平スライダーです。確かにスクロールのスナップを実現させるために、いくつかのJavaScriptがあります。「scroll-snap」のおかげで簡単にCSSで実装できるようになりました。「scroll-snap」をすべてに使用するべきではありません。記事ページなどでは、必要ないでしょう。イメージギャラリーやスライドーショー、そして縦長ページなどは適したコンテンツであると思いますが、それら以外にも潜在的な可能性があるという点で素晴らしい改善ができると思います。最後に細心の注意が払われていれば、スクロールのスナップは有用なツールになります。CSSのスナップポイントを使用すると、ブラウザのネイティブのスクロール操作を使用して、インターフェイスがシームレスでスムーズに感じられます。APIがあれば、さらに強力になるでしょう。軽くタッチするだけで、簡単に進めることができます。