📜

JavaScriptでスクロール処理を実装するのに便利なscrollIntoViewがAndroid Chromeで動かなくて焦った件

2024/06/17に公開

スクロール処理の実装に便利な scrollIntoView

Webページ内の特定の要素を画面に表示される領域までスクロールさせることができます。

しかも、簡潔に実装できます。とっても便利です。

const targetElement = document.getElementById('elementId');
targetElement?.scrollIntoView();

window.scrollwindow.scrollTo などを利用して、同挙動を実現することは可能です。

ただ、特定の要素の位置座標を取得するロジックが必要になるなど、scrollIntoView より多くの処理が必要となります。

scrollIntoView は最新のブラウザでサポートされており、スムーススクロールの設定も簡単にできるので、スクロール処理を実装する際の有力な選択肢になりそうです。

https://developer.mozilla.org/ja/docs/Web/API/Element/scrollIntoView

AndroidのGoogle Chromeでの問題(2024年6月時点)

モーダルが閉じる直前に、その裏側の(モーダル表示時に隠れている)コンテンツ内の特定要素を画面に表示される領域までスクロールさせる処理を scrollIntoView を使って実装していました。

PC、iOS端末の各ブラウザでは上記挙動を実現できますが、AndroidのChromeのみスクロール処理が走っていませんでした。Chrome DevToolsでも再現できず、実機のみ発生する問題のようです。

scrollIntoViewが動作しないケース

  • 実行対象が存在しない、または適切に設定されていない
  • 実行対象に display: none もしくは visibility: hidden が適用されている

今回のケースでは、実行対象は存在し、非表示にするCSSも適用されていませんでした。

それなのにスクロールが実行されなかった理由

以下要因が重なってしまったことが原因でした。

  • モーダル表示時、bodyoverflow: hidden を適用して背景スクロールを抑止していた
  • モーダル内でスクロールが行えるように overflow: auto を設定していた

スクロールが実行されなくなった理由として、想定される処理の流れは以下の通りです。

  1. 対象となる要素の祖先要素となるbodyoverflow: hidden が適用される
  2. スクロールさせられる対象がbodyから、スクロール可能かつ表示状態であるモーダルウィンドウに変わる
  3. 対象要素はモーダルウィンドウ内に存在しないため、スクロールが実行されない

対処方法

bodyoverflow: hidden を設定しない

背景スクロールを他の方法で抑止できれば上記設定は不要です。以下の記事が参考になります。

https://ics.media/entry/221024/

scrollIntoView の代わりに window.scrollwindow.scrollTo を使う

対象要素を表示領域の上端までスクロールさせるための実装例です。

const targetElement = document.getElementById('elementId');
if (targetElement) {
  const rect = element.getBoundingClientRect();
  window.scrollTo({ top: rect.top + window.scrollY });
}

scrollIntoView を利用すれば、上端、中央、下端、近い方の端などオプションで簡単かつ直感的に設定できるメリットがあるので、可能なら①を採用したいところですね。

今回の記事は以上になります。最後まで読んでいただき、ありがとうございました。

LCL Engineers

Discussion