Chrome 129 以降では、JavaScript の scrollSnapChange
イベントと scrollSnapChanging
イベントを使用できます。組み込みのスナップイベントを実装することで、これまでは非表示だったスナップ状態が、適切なタイミングで、常に正確に操作可能になります。これらのイベントがなければ、このような利便性はありませんでした。
scrollSnapChange
より前は、交差点オブザーバーを使用してスクロール ポートを横切る要素を見つけることができましたが、スナップされた要素の特定はいくつかの状況に限定されていました。たとえば、スナップ アイテムがスクロール ポートを埋めているか、スクロール ポートの大部分を占めているかを検出できます。そのためには、スクロール領域の交差する要素を監視し、どのアイテムがスクロール領域の大部分を消費しているかに基づいて、これがスナップ ターゲットであると想定し、scrollend
を待ってからスナップされたアイテム(スナップ ターゲット)を処理します。
しかし、scrollSnapChanging
より前は、スナップ ターゲットがいつ変化しているか、(スクロール フリングなどで)何が変更されたかを知ることは不可能でした。
これらの新しいイベントでは、このような情報をすばやく簡単に確認できます。これにより、スクロール スナップの操作が現在の機能を超えて広がり、スクロール スナップの関係と最新の UI フィードバック シナリオのオーケストレーションが可能になります。
scrollSnapChange
このイベントは、スクロール ジェスチャーによって新しいスナップ ターゲットが停止された場合にのみ、次の順序で発生します。
- スクロールが停止した後。
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')
}
スナップされたアイテムのキャプションを表示する
この例では、スナップされたアイテムのキャプションを示しています。このデモには両方のイベントが含まれているため、scrollSnapChange
と scrollSnapChanging
のタイミングとユーザー エクスペリエンスの違いを確認できます。
スナップされたプレゼンテーション スライドの子を 1 回アニメーション化する
この例では、新しいスライドが表示されて停止したときに、コンテンツを 1 回アニメーション化します。
document.addEventListener('scrollsnapchange', event => {
event.snapTargetBlock.classList.add('seen')
})
スクロールバーの x 軸と y 軸の両方でのスナップ
スクロール スナップは、水平方向と垂直方向のスクロールが可能なスクロールバーで機能します。このデモでは、グリッドをスクロールすると scrollSnapChanging
ターゲットと scrollSnapChange
ターゲットの両方が表示されます。このデモでは、ブラウザがスナップする要素が、想定している要素と一致しないことがあることを示します。
2 つのリンクされたスクロールバー
このデモには、2 つのスクロール スナップ コンテナがあります。1 つはリンクの概要リストで、もう 1 つは実際のページ分割コンテンツです。新しい scrollSnapChanging
イベントにより、これらのスナップ状態を双方向にリンクして、常に同期させることができます。
OKLCH カラー選択ツール
このデモには 3 つのスクローラーがあり、それぞれ OKLCH で異なるカラーチャンネルを表します。スナップされたアイテムは、関連するラジオ グループと同期され、入力をラップするフォームからデータを取得できます。マウスまたはタップを使用しているユーザーは、目的の値までスクロールできます。キーボードを使用している場合は、Tab キーと矢印キーを使用できます。スクリーン リーダーでは、これは単なるフォームです。
アニメーション ハブのずれとスナップ
このデモでは、scrollsnapchange
を使用してスナップがトリガーされる遷移で、スクロール スナップのエクスペリエンスを段階的に向上させています。
次の JavaScript を使用して、イベントのサポートを確認します。
if ('onscrollsnapchange' in window) {
// ok to use snap change
}
スクロール可能な定規入力
このデモでは、数値入力の長さを選択する代替方法として、スクロール可能な定規を使用しています。数値入力欄に値を直接入力するか、サイズまでスクロールします。changing イベントは、ユーザーの操作中に選択を消去するために使用されます。change イベントは、状態を更新してユーザーの選択を確定するために使用されます。
カバーフロー
このデモは、有名な macOS のカバーフローをBramus Van Damme が再現した優れたスクロール駆動アニメーション(動画チュートリアルも)に基づいています。scrollSnapChanging
はアルバム タイトルを非表示にするために、scrollSnapChange
はタイトルを表示するために使用されます。これらのイベントは、古いタイトルを早期に非表示にし、新しいタイトルを遅延して表示する際に役立ちます。
創造性を刺激するその他のアイデア
どの要素がスナップされ、どの要素がアクティブにスナップされているかを簡単に判別できるようになったため、さまざまな新しい可能性があります。創造性を刺激するアイデアとその他のユースケースを以下に示します。
- 遅延読み込みをトリガーする(Snapchange トリガー型レンダリングまたはデータ取得)
- 大きな画像にリンクされたフィルムストリップのサムネイル。
- スナップされた動画のサムネイルで動画予告編の再生/一時停止を切り替える。
- アナリティクスのトラッキング
- スクロール ストーリーテリング
- ホイールオブフォーチュンの UI/UX
- スナップ ターゲットにアンカー付きのツールチップが表示されます。
- タップしてスナップ
- スナップして表示
- スナップ時の音
- スワイプ UI
- スワイプ可能なタブまたはカルーセル
さらなる研究
Chrome チームは、これらの新しい API を使ってどのようなものを構築するか、ぜひお聞かせいただきたいと考えています。また、スクロール可能なエクスペリエンスの効率化に役立てていただけることを願っています。