スクロール スナップ イベント

Adam Argyle
Adam Argyle

Chrome 129 以降では、JavaScript の scrollSnapChange イベントと scrollSnapChanging イベントを使用できます。組み込みのスナップイベントを実装することで、これまでは非表示だったスナップ状態が、適切なタイミングで、常に正確に操作可能になります。これらのイベントがなければ、このような利便性はありませんでした。

対応ブラウザ

  • Chrome: 129。
  • Edge: 129。
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

ソース

対応ブラウザ

  • Chrome: 129。
  • Edge: 129。
  • Firefox: サポートされていません。
  • Safari: サポートされていません。

ソース

scrollSnapChange より前は、交差点オブザーバーを使用してスクロール ポートを横切る要素を見つけることができましたが、スナップされた要素の特定はいくつかの状況に限定されていました。たとえば、スナップ アイテムがスクロール ポートを埋めているか、スクロール ポートの大部分を占めているかを検出できます。そのためには、スクロール領域の交差する要素を監視し、どのアイテムがスクロール領域の大部分を消費しているかに基づいて、これがスナップ ターゲットであると想定し、scrollend を待ってからスナップされたアイテム(スナップ ターゲット)を処理します。

しかし、scrollSnapChanging より前は、スナップ ターゲットがいつ変化しているか、(スクロール フリングなどで)何が変更されたかを知ることは不可能でした。

スナップ ターゲットとして内部に番号の付いたボックスがある水平スクローラーが表示されています。左側は scrollSnapChange イベントのリアルタイム ログで、snapTargetInline が青色でハイライト表示されています。右側は、scrollSnapChanging イベントのリアルタイム ログです。snapTargetInline がグレーでハイライト表示されています。

試してみる
https://codepen.io/web-dot-dev/pen/jOjaaEP

これらの新しいイベントでは、このような情報をすばやく簡単に確認できます。これにより、スクロール スナップの操作が現在の機能を超えて広がり、スクロール スナップの関係と最新の UI フィードバック シナリオのオーケストレーションが可能になります。

scrollSnapChange

このイベントは、スクロール ジェスチャーによって新しいスナップ ターゲットが停止された場合にのみ、次の順序で発生します。

  1. スクロールが停止した後。
  2. scrollend より前。

このイベントは、スクロールが完了したときに scrollend の直前に発生します。ただし、新しいスナップ ターゲットに停止した場合に限られます。これにより、スクロール ジェスチャーが完了したときに、イベントが遅延またはジャストインタイムで発生するようになります。

scroller.addEventListener('scrollsnapchange', event => {
  console.log(event.snapTargetBlock);
  console.log(event.snapTargetInline);
})

scroller.onscrollsnapchange = event => {
  console.log(event.snapTargetBlock);
  console.log(event.snapTargetInline);
}

このイベントは、イベント オブジェクト上にスナップされたアイテムを snapTargetBlock および snapTargetInline として公開します。スクロールが水平方向のみの場合は、snapTargetBlock プロパティは null になります。プロパティの値は要素ノードです。

ScrollSnapChange 固有の詳細

ユーザーがジェスチャーを離すまで発動しません

画面上を指、またはトラックパッドに指がある場合、ユーザーの操作でスクロールが完了していません。つまり、スクロールが終了していません。つまり、スナップ ターゲットがまだ変更されておらず、ユーザー操作の完了を保留していることを意味します。

スナップ ターゲットが変更されていない場合、トリガーされません

このイベントはスナップ変更用です。スナップ ターゲットが変更されていなければ、ユーザーがスクローラーを操作してもイベントは起動しません。ユーザーは実際にスクロールしたため、スクロールが完了すると scrollend イベントがトリガーされます。

scrollSnapChanging

このイベントは、スクロール ジェスチャーによって新しいスナップ ターゲットが設定されたか、設定される予定であるとブラウザが判断した直後に発生します。スクロール中に即座に発生します。

scroller.addEventListener('scrollsnapchanging', event => {
  console.log(event.snapTargetBlock);
  console.log(event.snapTargetInline);
})

scroller.onscrollsnapchanging = event => {
  console.log(event.snapTargetBlock);
  console.log(event.snapTargetInline);
}

このイベントは、イベント オブジェクト上にスナップされたアイテムを snapTargetBlock および snapTargetInline として公開します。スクローラーが垂直方向のみの場合、snapTargetInline プロパティは null になります。プロパティの値は要素ノードになります。

scrollSnapChanging の固有の詳細

スクロール ジェスチャー中に早い段階で頻繁に発生する

ユーザーの完全なスクロール操作を待機する scrollSnapChange とは異なり、このイベントはユーザーが指またはトラックパッドを使用してスクロールすると積極的に呼び出されます。指を離さずにゆっくりとスクロールしているユーザーの場合、ユーザーが複数のスナップ ターゲット上でパンしている限り、scrollSnapChanging はジェスチャー中に複数回呼び出されます。ユーザーがスクロールするたびに、ブラウザがリリース時に新しいスナップ ターゲットに停止すると判断した場合、その要素を示すイベントが発生します。

新しいスナップ ターゲットまでの経路にあるすべてのスナップ ターゲットがトリガーされない

さらに、ユーザーが複数のスナップ ターゲットにまたがって一度にスクロールするスロー ジェスチャーを行うフリングについて考えてみましょう。このイベントは、ターゲットとなるターゲットで 1 回発生します。スナップ ターゲットをできるだけ早く提供し、無駄を省きます。

ユースケースと例

これらのイベントにより、多くの新しいユースケースが可能になるとともに、現在のパターンを簡単に実装できるようになります。その一例が、スナップによってトリガーされるアニメーションの有効化です。スナップ アイテム、スナップ アイテムの子、またはスナップ ターゲットである場合に関連する情報を、コンテキストに応じて表示する。

次のパターンは、すぐに生産性を高めるのに役立つユースケースを示しています。

お客様の声をハイライト表示する

この例は、スナップされたお客様の声を宣伝したり、視覚的に焦点を合わせたりしています。

scroller.onscrollsnapchange = event => {
  scroller.querySelector(':scope .snapped')?.classList.remove('snapped')
  event.snapTargetInline.classList.add('snapped')
}
https://codepen.io/web-dot-dev/pen/dyBZZPe

スナップされたアイテムのキャプションを表示する

この例では、スナップされたアイテムのキャプションを示しています。このデモには両方のイベントが含まれているため、scrollSnapChangescrollSnapChanging のタイミングとユーザー エクスペリエンスの違いを確認できます。

スナップの変更
https://codepen.io/web-dot-dev/pen/wvLPPBL

スナップ変更
https://codepen.io/web-dot-dev/pen/QWXOObw

スナップされたプレゼンテーション スライドの子を 1 回アニメーション化する

この例では、新しいスライドが表示されて停止したときに、コンテンツを 1 回アニメーション化します。

document.addEventListener('scrollsnapchange', event => {
  event.snapTargetBlock.classList.add('seen')
})
https://codepen.io/web-dot-dev/pen/rNEYYVj

スクロールバーの x 軸と y 軸の両方でのスナップ

スクロール スナップは、水平方向と垂直方向のスクロールが可能なスクロールバーで機能します。このデモでは、グリッドをスクロールすると scrollSnapChanging ターゲットと scrollSnapChange ターゲットの両方が表示されます。このデモでは、ブラウザがスナップする要素が、想定している要素と一致しないことがあることを示します。

横方向と縦方向のスクロール可能な正方形のグリッドが表示されます。破線の枠線は scrollSnapChanging ターゲット、実線の枠線は scrollSnapChange ターゲットを表します。赤は snapTargetInline、青は snapTargetBlock を表します。

https://codepen.io/web-dot-dev/pen/qBzVVdp

2 つのリンクされたスクロールバー

このデモには、2 つのスクロール スナップ コンテナがあります。1 つはリンクの概要リストで、もう 1 つは実際のページ分割コンテンツです。新しい scrollSnapChanging イベントにより、これらのスナップ状態を双方向にリンクして、常に同期させることができます。

https://codepen.io/web-dot-dev/pen/YzoEEXj

OKLCH カラー選択ツール

このデモには 3 つのスクローラーがあり、それぞれ OKLCH で異なるカラーチャンネルを表します。スナップされたアイテムは、関連するラジオ グループと同期され、入力をラップするフォームからデータを取得できます。マウスまたはタップを使用しているユーザーは、目的の値までスクロールできます。キーボードを使用している場合は、Tab キーと矢印キーを使用できます。スクリーン リーダーでは、これは単なるフォームです。

scrollSnapChanging は、スナップされたアイテムを状態と早期に同期するために使用されます。scrollSnapChange は、ユーザー入力が適用された影響を受けるカラー チャンネル ヘッダーをアニメーション化するために使用されます。

https://codepen.io/web-dot-dev/pen/OJeOOVG

アニメーション ハブのずれとスナップ

このデモでは、scrollsnapchange を使用してスナップがトリガーされる遷移で、スクロール スナップのエクスペリエンスを段階的に向上させています。

次の JavaScript を使用して、イベントのサポートを確認します。

if ('onscrollsnapchange' in window) {
  // ok to use snap change
}
https://codepen.io/web-dot-dev/pen/MWMOOae

スクロール可能な定規入力

このデモでは、数値入力の長さを選択する代替方法として、スクロール可能な定規を使用しています。数値入力欄に値を直接入力するか、サイズまでスクロールします。changing イベントは、ユーザーの操作中に選択を消去するために使用されます。change イベントは、状態を更新してユーザーの選択を確定するために使用されます。

https://codepen.io/web-dot-dev/pen/LYKOOpd

カバーフロー

このデモは、有名な macOS のカバーフローをBramus Van Damme が再現した優れたスクロール駆動アニメーション動画チュートリアルも)に基づいています。scrollSnapChanging はアルバム タイトルを非表示にするために、scrollSnapChange はタイトルを表示するために使用されます。これらのイベントは、古いタイトルを早期に非表示にし、新しいタイトルを遅延して表示する際に役立ちます。

https://codepen.io/web-dot-dev/pen/Bagmmog

創造性を刺激するその他のアイデア

どの要素がスナップされ、どの要素がアクティブにスナップされているかを簡単に判別できるようになったため、さまざまな新しい可能性があります。創造性を刺激するアイデアとその他のユースケースを以下に示します。

  • 遅延読み込みをトリガーする(Snapchange トリガー型レンダリングまたはデータ取得)
  • 大きな画像にリンクされたフィルムストリップのサムネイル。
  • スナップされた動画のサムネイルで動画予告編の再生/一時停止を切り替える。
  • アナリティクスのトラッキング
  • スクロール ストーリーテリング
  • ホイールオブフォーチュンの UI/UX
  • スナップ ターゲットにアンカー付きのツールチップが表示されます。
  • タップしてスナップ
  • スナップして表示
  • スナップ時の音
  • スワイプ UI
  • スワイプ可能なタブまたはカルーセル

さらなる研究

Chrome チームは、これらの新しい API を使ってどのようなものを構築するか、ぜひお聞かせいただきたいと考えています。また、スクロール可能なエクスペリエンスの効率化に役立てていただけることを願っています。

リソース: