CSSのスクロールスナップの便利な使い方、実装の注意点を徹底解説

CSSのスクロールスナップが登場して早4年、現在ではほぼすべてのブラウザにサポートされ、採用しているWebサイトやスマホアプリも増えてきました。

CSSのスクロールスナップについて、基礎知識をはじめ、各プロパティの機能や使い方、スクロールスナップの実際の使用例、実装の注意点などを紹介します。

CSSのスクロールスナップの便利な使い方、実装の注意点を徹底解説

CSS Scroll Snap
by Ahmad Shadeed

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

はじめに

スクロール可能なコンテナを簡単に実装できるCSSの機能があったらと、望んだことがあると思います。CSSのスクロールスナップはそれを簡単に実現できます。

フロントエンド開発の初期の頃は、スライダーを実装するためにJavaScriptのプラグインに頼っていました。また、要素をスクロール可能なコンテナとしてすばやく実装する方法が必要になることもありました。
今日ではCSSのスクロールスナップのおかげで、それらが全部可能です。

スクロールスナップは現在、ほぼすべてのブラウザでサポートされています。

サイトのキャプチャ

スクロールスナップの対応ブラウザ

この記事では、CSSのスクロールスナップの基本から実際の使用方法までていねいに解説したいと思います。
準備はいいですか? さぁ始めましょう!

CSSのスクロールスナップを使う理由

スマホやタブレットの台頭に伴い、タッチ操作でスワイプできるコンポーネントを設計・構築する必要があります。

例えば、ギャラリーを例に考えてみましょう。ユーザーは階層構造よりも、左右のスワイプでより多くの画像を簡単に見ることができます。

ギャラリーのキャプチャ

タッチデバイスでは、左右のスワイプの方が簡単

CSSの仕様によると、デベロッパーによって適切に制御されたスクロールエクスペリエンスを提供することは、CSSのスクロールスナップが導入された理由の1つです。ユーザーエクスペリエンスを向上させるスクロールエクスペリエンスの実装が容易になります。

スクロールコンテナの基本

スクロールコンテナを作成するために必要なものは次のとおりです。

  • overflowプロパティをvisible以外の値で使用する。
  • アイテムを横に並べて(インラインで)表示する方法。

例を見てみましょう。

white-space: nowrap;はここ何年のもの間、要素を強制的にインラインにするための一般的なCSSのテクニックでした。しかし、このような使い方は本来のものとは異なるため、望んでいないでしょう。現在ではありがたいことに、これを回避して代わりにFlexboxで実現できます。

スクロールコンテナ

スクロールコンテナ

これはスクロールコンテナを作成するための基本的なコードです。とはいえ、これだけでは不十分で、まだ使い物にはなりません。

スクロール コンテナの注意点

スクロール コンテナの注意点はスワイプがどのように動作するかに比べて、優れたエクスペリエンスが提供されないことです。タッチスクリーンでのスワイプジェスチャーの主な利点は、1本の指で水平または垂直にスクロールできることです。

何もしないと、下記のような操作を強いられます。

各アイテムをそれぞれの場所に指で移動させるのはつらい

文字通り、各アイテムをそれぞれの場所に指で移動させる必要があります。これはスワイプと呼べるものではなく、非常に悪いエクスペリエンスです。CSSのスクロールスナップを使用することで、ユーザーが水平または垂直方向にスクロールしやすくなるスナップポイントを定義するだけで、この問題を解決できます。

CSSのスクロールスナップの使用方法を見てみましょう。

CSSのスクロールスナップとは

コンテナ上でスクロールスナップを使用するには、その子アイテムをインラインで表示する必要があり、これは前述した方法で実装できます。nowrapは古いテクニックなので、display: flex;を使用して実装します。

スクロールスナップを機能させるためには、さらに2つのプロパティを追加する必要があります。どこに追加すればいいのか? いい質問ですね。

まず、スクロールコンテナにscroll-snap-typeを追加します。この例では、.section要素がスクロールコンテナです。次に、子アイテムの.section__itemscroll-snap-alignを追加します。

x mandatorystartという値が気になるかもしれません。心配しないでください。これらが核心なので、後ほど詳しく解説します。

2つのプロパティを追加したことにより、開始点にスナップするスクロールコンテナが作成できました。

開始点にスナップするスクロールコンテナ

開始点にスナップするスクロールコンテナの完成

これを初めてみた時、私は興奮しました! スクロールがより自然になります。
では、スクロールスナップのプロパティについて詳しく解説します。

scroll-snap-typeプロパティとは

CSSの仕様によると、scroll-snap-typeとは要素がスクロールスナップコンテナかどうか、どの程度厳密にスナップするか、どの軸を考慮するかなどを定義するプロパティです。

スクロールスナップコンテナの軸とは、スクロールの方向を表します。水平または垂直にすることができ、x値は水平スクロール、y値は垂直スクロールを表します。

scroll-snap-typeプロパティ

x値は水平スクロール、y値は垂直スクロール

スクロールスナップコンテナの厳密さとは、scroll-snap-typeプロパティのもう1つの値としてmandatory | proximityを定義できます。

mandatory値は、ブラウザが各スクロールポイントにスナップする必要があることを意味します。scroll-snap-alignプロパティの値がstartであると仮定します。この時は、スクロールはスクロールコンテナの開始点にスナップしなければならないということです。

下記は、ユーザーが右にスクロールするたびに、ブラウザがアイテムをコンテナの開始点にスナップします。

mandatory値を使用した場合

mandatory値を使用した場合

mandatory値を使用した場合

mandatory値を使用した場合

さらに良いことに、下記のデモで右にスクロールしてみてください。スマホやタブレットなど、タッチ操作ができる環境でご覧ください。あなたは、各アイテムがコンテナの先頭にどのようにスナップするか体験できます。

See the Pen
Scroll Snap Strictness
by Ahmad Shadeed (@shadeed)
on CodePen.

しかし、値がproximityの場合はブラウザが仕事をします。定義されたポイントにスナップする可能性があります(この場合は開始点)。proximity値がデフォルト値なことに注意してください。

proximity値を使用した場合

proximity値を使用した場合

proximity値を使用した場合

proximity値を使用した場合

スクロールスナップの位置

スクロールコンテナの子アイテムには、スナップできる位置合わせポイントが必要です。start, center, endのいずれかを定義できます。

これらがどのように機能するかを視覚的に示しました。

スクロールスナップの位置

start, center, endの位置(水平の場合)

スクロールコンテナに磁石があり、スナップする位置を制御しているイメージです。scroll-snap-typeyで垂直の場合は、スナップの位置も垂直になります。

スクロールスナップの位置

start, center, endの位置(垂直の場合)

start, center, endの位置を明確にするために、下記をご覧ください。

スクロールコンテナのstartの位置

子アイテムは、スクロールコンテナの開始点にスナップします。

スクロールコンテナのstartの位置

スクロールコンテナのstartの位置

スクロールコンテナのcenterの位置

子アイテムは、スクロールコンテナの中央にスナップします。

スクロールコンテナのcenterの位置

スクロールコンテナのcenterの位置

スクロールコンテナのendの位置

子アイテムは、スクロールコンテナの終点にスナップします。

スクロールコンテナのendの位置

スクロールコンテナのendの位置

scroll-snap-stopの使い方

時には、スクロール中にユーザーが誤って重要なアイテムをスキップしてしまうのを防ぐ方法が必要になるかもしれません。ユーザーのスクロールが速いと、いくつかのアイテムをスキップしてしまう可能性があります。

スクロールが速い場合

スクロールが速いと、アイテムをスキップする可能性がある

scroll-snap-stopのデフォルト値は、normalです。すべてのポイントにスクロールを可能な限りスナップさせるには、alwaysを定義します。

scroll-snap-stop: always;にすると、各スナップポイントで停止します。

always値にした場合

always値は、各スナップポイントで停止する

always値を定義することで、ユーザーは一度に1つのスナップポイントまでスクロールすることができ、重要なアイテムをスキップすることを避けることができます。各スナップポイントにストップのサインがあると想像してみてください。

always値にした場合

always値は、各スナップポイントにストップのサインがあるイメージ

normalalwaysの挙動の違いは、下記のデモをご覧ください。

See the Pen
Scroll Snap Stop
by Ahmad Shadeed (@shadeed)
on CodePen.

scroll-paddingの使い方

scroll-paddingはショートハンドのプロパティで、paddingと同様に上下左右にスクロールのパディングを定義します。下記ではスクロールコンテナの左側に50pxのパディングを与えており、その結果子要素は左端から50pxにスナップします。

scroll-paddingの使用例

scroll-paddingの使用例(水平)

垂直のスクロールでも同様に機能します。

scroll-paddingの使用例

scroll-paddingの使用例(垂直)

scroll-marginの使い方

scroll-marginもショートハンドのプロパティで、スクロールコンテナの子アイテム間のスペースを定義します。要素にマージンが追加されると、スクロールはマージンに合わせてスナップします。

scroll-marginの使用例

scroll-marginの使用例

.item-2scroll-margin-left: 20px;を定義しています。その結果、スクロールコンテナはそのアイテムより前20pxにスナップします。ユーザーが再び右にスクロールすると、.item-3は開始点にスナップします。
つまり、マージンのある要素のみが影響を受けることを意味します。

CSSのスクロールスナップの使用例

画像のリスト

CSSのスクロールスナップの優れた使用例は、画像のリストです。スクロールスナップを使用すると、はるかに優れたスクロールエクスペリエンスが得られます。

画像のリスト

画像のリスト

scroll-snap-typeの値に、xを定義したことに注目してください。スナップの厳密さはproximityです。

See the Pen
Scroll Snap - Images List
by Ahmad Shadeed (@shadeed)
on CodePen.

友達のリスト

CSSのスクロールスナップのもう1つの優れた使用例は、友達のリストです。こちらは画像のみではなく、カードが使用されています。以下の例は、Facebookの使用例です。

友達のリスト

友達のリスト

スクロールコンテナにpadding-bottom: 32px;が定義されていることに注目してください。この目的は、box-shadowが期待通りに表示されるようにスペースを確保することです。

友達のリスト

上: paddingなし、下: paddingあり

アバターのリスト

この使用例では、子アイテムのscroll-snap-alignの値としてcenterを使用していることに注目してください。

アバターのリスト

アバターのリスト

centerを定義することで、スクロールコンテナの中央にあることが重要なアバターのリストで役立ちます。

See the Pen
Scroll Snap - Avatars
by Ahmad Shadeed (@shadeed)
on CodePen.

高さいっぱいのセクション

スクロールスナップは、垂直スクロールにも役立ちます。例えば、高さいっぱいのセクションです。

高さいっぱいのセクション

高さいっぱいのセクション

See the Pen
Scroll Snap - Full Height Sections
by Ahmad Shadeed (@shadeed)
on CodePen.

block値とinline値について

scroll-snap-typeプロパティでは、論理値としてblockinlineを使用できることは特筆に値します。

上記では、英語のような横書きモードではinlineは水平方向を表し、日本語のような縦書きモードではinlineは垂直方向を表します。

アクセシビリティ

スクロールスナップを使用するときは、アクセシビリティを確保してください。
ユーザーがコンテンツを自由にスクロールして読むことができないようにする悪い使用例を紹介します。

悪い使用例

記事を読むためにスクロールしたら、次の見出しに移動してしまう

実際の動作は、下記のデモでご覧ください。
※こんな実装は絶対にしないでください!

See the Pen
Scroll Snap - Accessibility - Bad Example
by Ahmad Shadeed (@shadeed)
on CodePen.

終わりに

コメントや提案があれば、@shadeed9までお願いします。

リソース

CSSのデバッグに関する電子書籍を書いていることをお知らせします。

サイトのキャプチャ

興味がある場合は、debuggingcss.comにアクセスして、本に関する最新情報を購読してください。

sponsors

top of page

©2020 coliss