TL;DR
- 2017年ごろから発生していた
scrollIntoView
を同時に複数実行すると 1つしか動作しないバグが存在する。*1 - 次バージョン v130 でやっと修正される予定*2
- それ以前のバージョンでサポートしたい場合は
scrollTo
を使うことで回避できる
scrollIntoView を同時に使う
scrollIntoView
という便利なプロパティが存在します。対象の要素にスクロールするためのものでスムーススクロールをする際によく使われるものかと思います。
ですが、Chrome のみ scrollIntoView
を同時に複数実行すると崩壊するバグが存在します。Safari や Firefox では問題なく同時実行できるので本当にバグです。また、手動でスクロールする際にも scrollIntoView
が止まってしまうようです。
scrollIntoView({behavior:'smooth'}) cancelled by user scroll or another call in unrelated scrolling box [40823405] - Chromium の issue にいい例があるのでぜひ試してみてください。
なんと v130 で修正される
以下の記事によると ウェブ版、Android版ともに v130 にて修正されていることが確認できます。実際、私がこの問題にハマったときは自分は Chrome Dev (v131) を使用していたため動作確認時に見逃してしまったということがありました。
v130 まで待てない場合
しかし、全員が Chrome を常に最新にしているわけではないのでバグが修正されてもしばらくはこの問題に対応しなければなりません。ありがたいことにこの問題は解決策が存在しており、以下の Stackoverflow で解説されています。
scrollIntoView
の代わりに scrollTo
を使用することで解決できるようです。複数 scrollIntoView
があればすべて scrollTo
に変える必要があります。
変え方は簡単で、scrollTo
は指定した X/Y 座標までスクロールするものなのでスクロールしたい要素の座標を計算して scrollTo
に渡すことができます。
例えば、以下のようなコードは
targetElement.scrollIntoView({ block: 'start', inline: 'nearest', behavior: 'smooth', });
このように変換ができそうです。
const targetY = targetElement.getBoundingClientRect().top + window.scrollY; window.scrollTo({ top: targetY, behavior: 'smooth', });
感想
Chrome だけ発生するバグはあまり踏んだことがなかったので結構面白かった。