thumbnail

HTML要素の位置を取得する方法とズレた場合の対処法

この記事では、ページの一番上からHTML要素までの大きさ、要素の位置の取得方法を説明します。ただし、JavaScriptのコードの記述場所に注意しないと取得した値がずれてしまいます。そこで、コードの記述位置に関して陥りがちなミスも伏せて説明します。

今回説明する要素の位置とは

今回説明する位置は、スクロールできる領域全てを含めた、ページ全体における要素の位置を表します。ページトップからターゲットまでの距離(px)と言ったほうが分かりやすいかもしれません。他の場所からの位置と区別するため、以下、この記事では絶対位置と呼びます。また、ターゲットの要素はビューポートの外にあっても構いません。

位置には横方向と縦方向がありますが、以下、話を簡単にするため縦方向(y方向)についてのみ考えます。

横方向(x方向)も同じ考え方です。

要素の絶対位置の取得方法

完成形のデモ

デモを用意しました。
取得した要素の絶対位置は右上の赤字で表示しております。
比較のため、現在のスクロール位置も同時に表示しました。

現在のスクロール位置の基準線をページの上端に青線で表示しています。

現在のスクロール位置である「青い線」がターゲット要素の上端の「赤い線」と重なった時、「絶対位置 = 現在のスクロール位置」となり、確かに絶対位置が得られていることがわかります。

それではコードの解説をしていきます。

絶対位置を取得するコード

絶対位置を取得するコードの例です。heightの値が絶対位置になります。

window.addEventListener('DOMContentLoaded', () => {
  height = element.getBoundingClientRect().top + window.scrollY
})

このコードは3つのステップで構成されています。

3つのステップ

  1. ビューポートからの位置を取得
  2. すでにスクロールされている場合を考慮
  3. 【重要】これらの位置の取得をDOM構築後に行う

コードの解説

ビューポートを基準としたの位置取得

絶対位置を取得する前に、ビューポートの左上を原点とした要素の位置を取得する必要があります。

ビューポートの左上を原点とした要素の位置を取得するには getBoundingClientRect()を使います。

const rect = element.getBoundingClientRect()

elementは対象要素です。

getBoundingClientRect()の主なプロパティは以下の通りです。

主なプロパティ

  • top: 要素の上までの長さ
  • left: 要素の左までの長さ
  • right: 要素の右までの長さ
  • bottom: 要素の下までの長さ
  • height: 要素の高さ
  • width: 要素の幅

詳しくはこちらのドキュメントをご覧ください。

高さ方向で関係するのはtopやbottomです。今回は要素の上部までの距離が知りたいので、topを利用します。

let top = element.getBoundingClientRect().top

これでtopの大きさが求まりました。

すでにスクロールされている場合を考慮

スクロール量を取得するコードは以下のようになります。

let scrolled = window.scrollY

window.pageYOffsetでもスクロール量が取得できますが、これはscrollYのエイリアスです。ただし、VS Codeで開発していると「pageYOffsetはレガシー(時代遅れ)なエイリアス」と表示され、打ち消し線が付き非推奨となっています。

このスクロール量(scrolled)とビューポートからの位置(top)を足すことで絶対位置を取得することができます。

scrolled + topが絶対位置になります。

注意点!取得した位置がずれる場合

絶対位置を求めるのはDOM構築後

注意すべきなのが、高さの取得はDOM構築後に行う必要があるところです。
つまりwindow.addEventListener('DOMContentLoaded', () => {})内で実行します。

DOM構築前に取得すると正しい位置が得られません。

また、imgタグにheightやwidthを指定して、画像の高さもあらかじめ定義しておいて下さい。(レイアウトシフト対策にもなります。)

まとめ

要素の絶対位置を取得する方法を紹介し、3つのステップに分けて見てきました。

3つのステップ

  1. ビューポートからの位置を取得
  2. すでにスクロールされている場合を考慮
  3. これらの位置の取得をDOM構築後に行う

特に3点目が重要で、DOM構築前に位置を取得するとズレてしまうので注意しましょう。
要素の位置が取得できれば、ページをどれだけ読み進めたか分かるプログレスバーなどに応用できます。