JavaScript 逆引き集 | smooth スクロール

JavaScript JavaScript
スポンサーリンク

スムーススクロールの基本 — window.scrollTo({ top: 0, behavior: 'smooth' })

「スムーススクロール」は、画面を指定位置まで滑らかに移動する演出です。ユーザーが「どこからどこへ移動したのか」を視覚的に理解しやすくなり、長いページでも迷いにくくなります。


基本の使い方

<button id="toTop">トップへ戻る</button>
<script>
  document.getElementById("toTop").addEventListener("click", () => {
    window.scrollTo({ top: 0, behavior: "smooth" });
  });
</script>
HTML
  • 役割: 画面のスクロール位置を「0」へ滑らかに移動。
  • 引数: top(目的の縦位置, px)、behavior: 'smooth'(滑らかに)。

よく使うテンプレート集

ラベル: 固定ヘッダーを避けてアンカーへスクロール

<header id="hdr" style="position: fixed; top:0; height: 64px; left:0; right:0;"></header>
<a href="#section2" id="link">セクション2へ</a>
<section id="section2" style="margin-top: 1000px;">ここが目的地</section>

<script>
  const hdr = document.getElementById("hdr");
  const link = document.getElementById("link");

  link.addEventListener("click", (e) => {
    e.preventDefault();
    const target = document.getElementById("section2");
    const r = target.getBoundingClientRect();
    const y = window.scrollY + r.top - hdr.offsetHeight; // ヘッダー分を差し引く
    window.scrollTo({ top: y, behavior: "smooth" });
  });
</script>
HTML

ラベル: 任意要素を画面中央に持ってくる

function scrollIntoCenter(el) {
  const r = el.getBoundingClientRect();
  const targetTop = window.scrollY + r.top - (window.innerHeight - r.height) / 2;
  window.scrollTo({ top: Math.max(targetTop, 0), behavior: "smooth" });
}
JavaScript

ラベル: コンテナ内をスムーススクロール

<div id="box" style="height: 200px; overflow: auto; border: 1px solid #ccc;">
  <div id="row50" style="height: 1000px; padding-top: 800px;">Row 50 付近</div>
</div>
<script>
  const box = document.getElementById("box");
  const row = document.getElementById("row50");
  function scrollItemIntoContainer(container, item) {
    const cr = container.getBoundingClientRect();
    const ir = item.getBoundingClientRect();
    const topInContainer = ir.top - cr.top + container.scrollTop;
    container.scrollTo({ top: topInContainer, behavior: "smooth" });
  }
  scrollItemIntoContainer(box, row);
</script>
HTML

実務でのコツ

  • ヘッダー補正: 固定ヘッダーがある場合は、その高さを目的位置から差し引いて視認性を確保。
  • アンカーリンクの上書き: e.preventDefault() でデフォルトのジャンプを止め、スムーススクロールへ置き換える。
  • 範囲の使い分け: 画面全体は window.scrollTo、スクロールコンテナは el.scrollTo
  • ユーザー操作の優先: 長距離移動はキャンセルしやすい設計に(例: 移動中のクリックで新操作を優先)。
  • CSSの補助: 一律で簡単に導入するなら html { scroll-behavior: smooth; } でもOK。ただし細かな制御はJSが向く。

ありがちなハマりポイントと対策

  • 固定ヘッダーで目的地が隠れる:
    • 対策: top - header.offsetHeight を計算して補正する。
  • コンテナでスクロールできない:
    • 原因: overflow: auto/scroll 未設定、または内容が短い。
    • 対策: overflow を設定し、内容の高さを確認。
  • モバイルで位置が揺れる(アドレスバー変動):
    • 対策: しきい値に余裕を持つ、再計算(resize/orientationchange)で補正。
  • サポート差異(古い環境):
    • 対策: 未対応ブラウザ向けにフォールバック(瞬間移動 behavior なし)を許容。

練習問題(アンカーリンクをスムース化)

<header id="hdr" style="position: fixed; top:0; left:0; right:0; height:56px; background:#eee;"></header>
<main style="margin-top:56px">
  <nav>
    <a class="js-smooth" href="#a">Aへ</a>
    <a class="js-smooth" href="#b">Bへ</a>
    <a class="js-smooth" href="#c">Cへ</a>
  </nav>
  <section id="a" style="height:800px; background:#f7f7f7">A</section>
  <section id="b" style="height:800px; background:#fafafa">B</section>
  <section id="c" style="height:800px; background:#f7f7f7">C</section>
</main>

<script>
  const header = document.getElementById("hdr");
  document.querySelectorAll("a.js-smooth[href^='#']").forEach(link => {
    link.addEventListener("click", (e) => {
      e.preventDefault();
      const id = link.getAttribute("href").slice(1);
      const target = document.getElementById(id);
      if (!target) return;
      const r = target.getBoundingClientRect();
      const y = window.scrollY + r.top - header.offsetHeight;
      window.scrollTo({ top: y, behavior: "smooth" });
    });
  });
</script>
HTML

直感的な指針

  • 画面は window.scrollTo({ top, behavior: 'smooth' })、コンテナは el.scrollTo({ top, behavior: 'smooth' })
  • 固定ヘッダーや目的の見え方を考慮して、位置を計算してからスクロールする。
  • デフォルトのアンカー動作は止め、スムース移動に置き換えると体験が綺麗。
タイトルとURLをコピーしました