JavaScript | DOM 操作:要素の位置・サイズ・スクロール – boundingClientRect

JavaScript JavaScript
スポンサーリンク

getBoundingClientRect とは何か

getBoundingClientRect は、要素の「画面(ビューポート)に対する位置とサイズ」を返すメソッドです。返ってくる値は小数を含む CSS ピクセルで、スクロールやズーム、CSS 変形(transform)の影響が反映されます。ここが重要です:ページ内の相対座標(offsetTop/Left)ではなく“今見えている画面”基準の座標を得られるため、ポップアップの位置合わせ、可視判定、交差判定など“画面目線”の処理に最適です。


返されるプロパティ(意味と使いどころ)

基本プロパティの意味

  • left/top: 画面左上から見た要素の左端・上端の位置(負になることもある)
  • right/bottom: 要素の右端・下端の位置(ビューポート基準)
  • width/height: 要素の見た目の幅・高さ(padding と border を含む。margin は含まない)
  • x/y: left/top と同義のショートハンド

ここが重要です:値は小数(サブピクセル)になり得ます。精密な重なり判定や線形補間が必要な処理では、この“小数の正確さ”が効きます。

スクロール・ズーム・変形の影響

  • スクロール: rect は常に画面基準。スクロールすると値が変わります。
  • ズーム: 値は CSS ピクセルで返るため、見え方に準じて変化します。
  • transform: scale/translate などの変形は rect に反映されます(変形後の見た目の箱)。

ここが重要です:見え方に合わせた UI(ツールチップ位置、当たり判定)をしたいなら rect が唯一の正解です。


基本の使い方(画面座標の取得とページ座標への変換)

画面座標を読む

<div id="box" style="width:160px; height:80px; border:1px solid #333">内容</div>
<script>
  const r = box.getBoundingClientRect();
  console.log(r.left, r.top, r.width, r.height);
}
</script>
HTML

ここが重要です:getBoundingClientRect() は“いまの画面に対して”の位置とサイズ。スクロールやズームを意識せず、常に正しい画面座標が取れます。

ページ左上からの絶対座標に変換する

<script>
  const r = box.getBoundingClientRect();
  const pageLeft = window.scrollX + r.left;
  const pageTop  = window.scrollY + r.top;
</script>
HTML

ここが重要です:ページ基準の絶対座標が必要なら、rect に現在のスクロール量(scrollX/scrollY)を足し込みます。固定ヘッダの補正などもこの組み合わせで行います。


代表的なユースケース(ポップアップ、可視判定、当たり判定)

要素に対してツールチップを正確に配置

<div id="btn">ボタン</div>
<div id="tip" style="position:fixed; display:none">ヒント</div>
<script>
  function showTip(anchor, tip) {
    const r = anchor.getBoundingClientRect();
    tip.style.left = (r.left + r.width / 2) + "px";
    tip.style.top  = (r.bottom + 8) + "px"; // 8px 下に出す
    tip.style.display = "block";
  }
  showTip(btn, tip);
</script>
HTML

ここが重要です:position: fixed と rect のペアは、画面基準の位置合わせに強い組み合わせです。スクロールしても位置が崩れません。

画面内に見えているかを判定(マージン付き)

<script>
  function isInViewport(el, margin = 0) {
    const r = el.getBoundingClientRect();
    return r.bottom > -margin && r.top < window.innerHeight + margin &&
           r.right  > -margin && r.left < window.innerWidth  + margin;
  }
  console.log("見えている?", isInViewport(document.getElementById("box"), 50));
</script>
HTML

ここが重要です:可視判定は rect と画面サイズ(innerWidth/innerHeight)で十分です。margin を持たせると“近づいたら先にロード”のような先読みができます。

当たり判定(要素どうしの交差)

<script>
  function intersects(a, b) {
    const ra = a.getBoundingClientRect();
    const rb = b.getBoundingClientRect();
    return !(ra.right < rb.left || ra.left > rb.right || ra.bottom < rb.top || ra.top > rb.bottom);
  }
</script>
HTML

ここが重要です:2つの矩形が重なっているかは、四辺の比較で判定できます。ドラッグ&ドロップやハイライトに応用できます。


offset/client と rect の使い分け(基準の違い)

それぞれの基準

  • offsetLeft/Top: offsetParent(レイアウト上の基準の親)に対する相対位置。外側寸法は offsetWidth/Height(整数)。
  • clientWidth/Height: 内側領域(content+padding)。スクロールバー・border なし(整数)。
  • boundingClientRect: 画面に対する位置とサイズ。スクロール・ズーム・transform 反映(小数)。

ここが重要です:親内のレイアウト計算やドラッグ基準なら offset、内側レイアウトなら client、画面目線の位置合わせ・可視判定なら rect。目的に合わせて基準を選ぶと計算がシンプルになり、ズレが消えます。


スクロールと固定ヘッダの“隠れない”補正

固定ヘッダで隠れない位置にスクロール

<header style="position:sticky; top:0; height:64px"></header>
<section id="target" style="margin-top:1000px">目的地</section>
<script>
  function scrollToVisibleTop(el, header = 0) {
    const r = el.getBoundingClientRect();
    const y = window.scrollY + r.top - header;
    window.scrollTo({ top: Math.max(y, 0), behavior: "smooth" });
  }
  scrollToVisibleTop(target, 64);
</script>
HTML

ここが重要です:rect.top は画面基準の位置。スクロール量を足し、ヘッダ高さを引けば、ちょうど見える位置に止まります。


パフォーマンスと注意点(計測→更新の順序、非表示、インライン)

レイアウトスラッシングを避ける

  • 計測と更新の分離:
    ポイント: まず getBoundingClientRect で“読む”(計測)→ 次のフレームで“書く”(スタイル更新)。requestAnimationFrame を使うと安全。
  • まとめて計測:
    複数要素の rect が必要なら、1フレーム内でまとめて読み、その後まとめて更新する。

ここが重要です:計測と更新を交互に混ぜると再レイアウトが多発し、カクつきます。順序を分けるのがコツです。

display: none の要素は 0 を返す

非表示(display: none)はレイアウト計算されないため、rect は 0 になります。事前計測したい場合は visibility: hidden(見えないがレイアウト参加)にして測りましょう。ここが重要です:“見え方の箱”という定義に沿った計測が必要です。

インライン要素が折り返す場合

getBoundingClientRect は“全体の外接矩形”を返します。行をまたぐテキストなど“各行の矩形”が欲しいなら getClientRects() を使います。ここが重要です:外接矩形では上下に余分が入ることがあるため、用途に応じて API を選びます。


まとめ

getBoundingClientRect は、要素の「画面(ビューポート)に対する正確な位置とサイズ」を小数で返すメソッドです。スクロール・ズーム・transform を反映し、ポップアップの配置、可視判定、交差判定、固定ヘッダ補正付きスクロールなど“画面目線”の処理に不可欠です。offset/client と基準が違うため、目的に応じた使い分けを徹底すると計算が短く、ズレのない UI が作れます。計測と更新の順序を分け、非表示やインラインの特性に注意すれば、初心者でも直感的に扱える堅実な実装ができます。

タイトルとURLをコピーしました