JavaScript 逆引き集 | getBoundingClientRect で座標取得

JavaScript JavaScript
スポンサーリンク

要素の座標取得の基本 — el.getBoundingClientRect() と表示制御(classList.toggle('is-hidden'))

要素の「画面上での位置とサイズ」を取りたいときは getBoundingClientRect()。返ってくる DOMRect から、上(top)/左(left)/幅(width)/高さ(height)などがピクセルで分かります。取得した座標を使ってツールチップを配置したり、見える/見えないで表示を切り替えたりできます。


返り値とよく使うプロパティ

const rect = el.getBoundingClientRect();
console.log(rect.top, rect.left, rect.width, rect.height);
console.log(rect.right, rect.bottom); // 右端・下端
console.log(rect.x, rect.y);          // left/top と同値(ブラウザ依存で同義)
JavaScript
  • 基準: ビューポート(画面の見えている領域)の左上が原点。スクロールすると値は変わります。
  • 内容: width/height は border と padding を含む「見えている箱」のサイズ。
  • 単位: ピクセル。小数になることもあります(拡大縮小やサブピクセル)。

例題1: ボタンの横にツールチップを正確に配置

<button id="info">情報</button>
<div id="tip" class="tip is-hidden">詳細ヘルプ</div>

<style>
  .tip { position: fixed; background: #333; color: #fff; padding: 6px 8px; border-radius: 4px; }
  .is-hidden { display: none; }
</style>

<script>
  const btn = document.getElementById("info");
  const tip = document.getElementById("tip");

  btn.addEventListener("click", () => {
    const r = btn.getBoundingClientRect(); // 画面上の位置とサイズ
    tip.style.left = `${r.right + 8}px`;   // ボタン右端から8px右
    tip.style.top  = `${r.top}px`;         // ボタンの上端に揃える
    tip.classList.toggle("is-hidden");     // 表示/非表示を切り替え
  });

  // スクロール時も位置が画面基準で合うよう、position: fixed を採用
</script>
HTML
  • ポイント: position: fixed を使うと、rect の値(画面基準)と座標指定が一致して楽です。
  • 補足: position: absolute を使う場合は、ページスクロール量 window.scrollX/scrollY を加算して調整します。

例題2: 画面内に見えているかで表示を切り替え

<div id="panel" class="panel is-hidden">コンテンツ</div>
<button id="toggle">見えるときだけ表示</button>

<style>
  .panel { position: fixed; right: 16px; bottom: 16px; background: #eee; padding: 8px; }
  .is-hidden { display: none; }
</style>

<script>
  const panel = document.getElementById("panel");
  const btn = document.getElementById("toggle");

  function inViewport(el) {
    const r = el.getBoundingClientRect();
    const vw = window.innerWidth;
    const vh = window.innerHeight;
    return r.bottom > 0 && r.top < vh && r.right > 0 && r.left < vw;
  }

  btn.addEventListener("click", () => {
    const visible = inViewport(btn);
    panel.classList.toggle("is-hidden", !visible); // ボタンが画面内なら表示
  });

  window.addEventListener("resize", () => {
    const visible = inViewport(btn);
    panel.classList.toggle("is-hidden", !visible);
  });
</script>
HTML
  • ポイント: 矩形がビューポートと重なっているかで判定。resize/scroll に応じて更新します。
  • 応用: 特定エリアに入ったらヘッダーを出す、下に来たら「トップへ戻る」ボタンを出すなど。

例題3: 絶対配置でツールチップ(スクロール補正あり)

<button id="save" style="margin-top: 1000px;">保存</button>
<div id="tip" class="tip is-hidden">保存の説明</div>

<style>
  .tip { position: absolute; background: #333; color: #fff; padding: 6px 8px; }
  .is-hidden { display: none; }
</style>

<script>
  const btn = document.getElementById("save");
  const tip = document.getElementById("tip");

  btn.addEventListener("click", () => {
    const r = btn.getBoundingClientRect();
    const x = r.right + 8 + window.scrollX; // ページ座標に変換
    const y = r.top + window.scrollY;

    tip.style.left = `${x}px`;
    tip.style.top = `${y}px`;
    tip.classList.toggle("is-hidden");
  });
</script>
HTML
  • ポイント: 画面基準の rect に、ページスクロール量を加えると「ページ座標」で配置できます。
  • 使い分け: fixed(楽・スクロール追従) vs absolute(ページ座標に合わせたいとき)。

実務でのコツとハマりやすい点

  • 計算タイミング:
    • ラベル: CSSのアニメーションやトランスフォーム中は値が動く。必要なフレームで計算するか requestAnimationFrame を使う。
  • スケール/ズーム:
    • ラベル: 拡大縮小(transform: scale)やブラウザズームで小数値になる。四捨五入は目的に応じて。
  • 境界衝突の処理:
    • ラベル: 右端でハミ出す場合は Math.min(r.right + 8, window.innerWidth - tip.offsetWidth - 8) のようにクリップ。
  • 再レイアウト:
    • ラベル: getBoundingClientRect() はレイアウト計算を引き起こすことがある。大量呼び出しはまとめて、不要な再計算を避ける。

練習問題(配置と表示の組み合わせを体験)

<button id="btn">ヘルプ</button>
<div id="help" class="bubble is-hidden">ここに説明が出ます</div>

<style>
  .bubble { position: fixed; background: #222; color: #fff; padding: 8px 10px; border-radius: 6px; }
  .is-hidden { display: none; }
</style>

<script>
  const btn = document.getElementById("btn");
  const help = document.getElementById("help");

  function placeBubble(anchor, bubble) {
    const r = anchor.getBoundingClientRect();
    bubble.style.left = `${r.left}px`;
    bubble.style.top  = `${r.bottom + 8}px`; // アンカーの下に 8px
  }

  btn.addEventListener("click", () => {
    placeBubble(btn, help);
    help.classList.toggle("is-hidden");
  });

  window.addEventListener("resize", () => {
    if (!help.classList.contains("is-hidden")) placeBubble(btn, help);
  });
</script>
HTML
  • 課題: 画面幅が狭いときは気持ち右寄せにする、などのクリップ処理を追加してみてください。

直感的な指針

  • 位置は getBoundingClientRect()、見せる/隠すは classList.toggle('is-hidden')
  • fixed ならそのまま座標指定、absolute なら scrollX/scrollY を加算。
  • ビューポートと境界の関係を意識して、クリップ・再計算のタイミングを整える。
タイトルとURLをコピーしました