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

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

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

相互運用性

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

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

背景

CSS のスクロール スナップ

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

  • スクロール時に不自然なスクロール位置が表示されないようにします。
  • コンテンツをページングする効果を作成します。

スクロール スナップの一般的なユースケースは、ページネーションされた記事と画像カルーセルです。

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 エンジニアに伝えてください