
ブログをNext.js14(App Router)でリファクタリングしました
この記事では、ページの一番上からHTML要素までの大きさ、要素の位置の取得方法を説明します。ただし、JavaScriptのコードの記述場所に注意しないと取得した値がずれてしまいます。そこで、コードの記述位置に関して陥りがちなミスも伏せて説明します。
目次
今回説明する位置は、スクロールできる領域全てを含めた、ページ全体における要素の位置を表します。ページトップからターゲットまでの距離(px)と言ったほうが分かりやすいかもしれません。他の場所からの位置と区別するため、以下、この記事では絶対位置と呼びます。また、ターゲットの要素はビューポートの外にあっても構いません。
位置には横方向と縦方向がありますが、以下、話を簡単にするため縦方向(y方向)についてのみ考えます。
横方向(x方向)も同じ考え方です。
デモを用意しました。
取得した要素の絶対位置は右上の赤字で表示しております。
比較のため、現在のスクロール位置も同時に表示しました。
現在のスクロール位置の基準線をページの上端に青線で表示しています。
現在のスクロール位置である「青い線」がターゲット要素の上端の「赤い線」と重なった時、「絶対位置 = 現在のスクロール位置」となり、確かに絶対位置が得られていることがわかります。
それではコードの解説をしていきます。
絶対位置を取得するコードの例です。heightの値が絶対位置になります。
window.addEventListener('DOMContentLoaded', () => {
height = element.getBoundingClientRect().top + window.scrollY
})
このコードは3つのステップで構成されています。
3つのステップ
絶対位置を取得する前に、ビューポートの左上を原点とした要素の位置を取得する必要があります。
ビューポートの左上を原点とした要素の位置を取得するには getBoundingClientRect()を使います。
const rect = element.getBoundingClientRect()
elementは対象要素です。
getBoundingClientRect()の主なプロパティは以下の通りです。
主なプロパティ
詳しくはこちらのドキュメントをご覧ください。
高さ方向で関係するのはtopやbottomです。今回は要素の上部までの距離が知りたいので、topを利用します。
let top = element.getBoundingClientRect().top
これでtopの大きさが求まりました。
スクロール量を取得するコードは以下のようになります。
let scrolled = window.scrollY
window.pageYOffsetでもスクロール量が取得できますが、これはscrollYのエイリアスです。ただし、VS Codeで開発していると「pageYOffsetはレガシー(時代遅れ)なエイリアス」と表示され、打ち消し線が付き非推奨となっています。
このスクロール量(scrolled)とビューポートからの位置(top)を足すことで絶対位置を取得することができます。
scrolled + topが絶対位置になります。
注意すべきなのが、高さの取得はDOM構築後に行う必要があるところです。
つまりwindow.addEventListener('DOMContentLoaded', () => {})
内で実行します。
DOM構築前に取得すると正しい位置が得られません。
また、imgタグにheightやwidthを指定して、画像の高さもあらかじめ定義しておいて下さい。(レイアウトシフト対策にもなります。)
要素の絶対位置を取得する方法を紹介し、3つのステップに分けて見てきました。
3つのステップ
特に3点目が重要で、DOM構築前に位置を取得するとズレてしまうので注意しましょう。
要素の位置が取得できれば、ページをどれだけ読み進めたか分かるプログレスバーなどに応用できます。
最新の記事
カテゴリー一覧
アーカイブ