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

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);
}

このイベントは、スナップされたアイテムをイベント オブジェクトの snapTargetBlocksnapTargetInline として公開します。スクロールが水平方向のみの場合は、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);
}

このイベントは、スナップされたアイテムをイベント オブジェクトの snapTargetBlocksnapTargetInline として公開します。スクロールが垂直方向のみの場合は、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

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

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

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

さらなる研究

Chrome チームは、これらの新しい API を使ってどのようなアプリを構築するか、楽しみにしています。また、スクロール可能なエクスペリエンスの効率化に役立つことを願っています。

リソース: