レイアウト変更後のスクロール スナップ

Chrome 81 以降では、強制的に再ナップするためにイベント リスナーを追加する必要がなくなります。

CSS スクロール スナップを使用すると、ウェブ デベロッパーはスクロールのスナップ位置を宣言することで、適切に制御されたスクロール エクスペリエンスを実現できます。現在の実装の欠点の一つは、ビューポートのサイズを変更したときやデバイスを回転したときなど、レイアウトが変更されたときにスクロール スナップが適切に機能しないことです。この欠点は Chrome 81 で修正されています。

相互運用性

多くのブラウザは、CSS のスクロール スナップの基本的な機能をサポートしています。詳しくは、CSS のスクロール スナップを使うことはできますか?をご覧ください。

現在、レイアウト変更後のスクロール スナップを実装するブラウザは Chrome だけです。Firefox ではこれを実装するためのチケットが公開されており、Safari ではスクローラーのコンテンツが変更された後に再スナップするためのオープンチケットも用意されています。現時点では、次のコードをイベント リスナーに追加して、スナップを強制的に実行することで、この動作をシミュレートできます。 javascript scroller.scrollBy(0,0); ただし、スクローラーが同じ要素にスナップバックするとは限りません。

背景

CSS スクロール スナップ

ウェブ デベロッパーは、CSS のスクロール スナップ機能を使用して、スクロールのスナップ位置を宣言することで、適切に制御されたスクロール エクスペリエンスを作成できます。このように配置することで、スクロール可能なコンテンツがコンテナに適切に配置され、不正確なスクロールの問題が解消されます。つまり、スクロールのスナップは次のようになります。

  • スクロール時に不自然なスクロール位置を回避します。
  • コンテンツをページ分割する効果を生み出します。

スクロール スナップの一般的なユースケースとして、ページネーションされた記事と画像カルーセルの 2 つがあります。

CSS のスクロール スナップの例。
CSS のスクロール スナップの例。スクロールの最後に、画像の水平方向の中央がスクロール コンテナの水平方向の中央に揃えられます。

欠点

ウィンドウのサイズを変更すると、スナップ位置が失われます。

スクロール スナップを使用すると、ユーザーはコンテンツ間を簡単に移動できますが、コンテンツの変更に適応できないため、潜在的なメリットの一部しか得られません。上のに示すように、ウィンドウのサイズを変更するたびに、以前にスナップされた要素を見つけるためにスクロール位置を再調整する必要があります。レイアウトが変更される一般的なシナリオは次のとおりです。

  • ウィンドウのサイズ変更
  • デバイスを回転させる
  • DevTools を開く

最初の 2 つのシナリオでは、CSS のスクロール スナップはユーザーにとってあまり魅力的ではありません。3 つ目のシナリオは、デベロッパーがデバッグする際の悪夢です。デベロッパーは、コンテンツの追加、削除、移動などのアクションをサポートする動的なエクスペリエンスを実現する場合も、このような欠点を考慮する必要があります。

これに対する一般的な修正は、JavaScript を介してプログラムによるスクロールを実行するリスナーを追加して、上記のレイアウト変更のいずれかが発生するたびにスナップを強制的に実行することです。この回避策は、ユーザーがスクローラーを以前と同じコンテンツにスナップして戻そうと期待している場合は、効果がない場合があります。JavaScript でさらに処理すると、この CSS 機能の目的が損なわれるところです。

レイアウト変更後の再スナップの組み込みサポート(Chrome 81)

前述の欠点は、Chrome 81 にはなくなりました。レイアウトを変更した後も、スクローラーはスナップしたままになります。レイアウトを変更した後にスクロール位置を再評価し、必要に応じて最も近いスナップ位置に再スナップします。スクローラーがレイアウト変更後も存在する要素にスナップされていた場合、スクローラーはその要素にスナップしようとします。次のでは、レイアウトが変更されたときにどうなるかに注目してください。

スナップ位置が失われました
Chrome 80 では、デバイスを回転させてもスナップ位置は保持されませんNOPE というスライドまでスクロールしてデバイスの向きを縦向きから横向きに変更すると、空白の画面が表示されます。これは、スクロールのスナップ位置がなくなったことを示します。
スナップ位置を保持しました
Chrome 81 では、デバイスを回転してもスナップ位置が保持される。デバイスの向きが複数回変化しても、「NOPE」と表示されたスライドは表示されたままになります。

詳しくは、レイアウト変更後の再スナップの仕様をご覧ください。

例: 固定スクロールバー

「レイアウト変更後にスナップ」機能を使用すると、デベロッパーは数行の CSS で固定スクロールバーを実装できます。

.container {
  scroll-snap-type: y proximity;
}

.container::after {
  scroll-snap-align: end;
  display: block;
}

詳しくは、ビジュアルについては、次のデモチャット UI をご覧ください。

新しいメッセージを追加すると再取得がトリガーされ、Chrome 81 では下部に固定されます。

今後の作業

現在、再スナップのスクロール効果はすべて即時に行われますが、今後、スムーズなスクロール効果による再スナップのサポートが検討される可能性があります。詳しくは、仕様に関する問題をご覧ください。

フィードバック

皆様からのフィードバックは、レイアウト変更後の再スナップを改善するうえで非常に貴重なものです。ぜひお試しいただき、Chromium のエンジニアにご意見をお寄せください