スムーススクロールの基本 — 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' })。 - 固定ヘッダーや目的の見え方を考慮して、位置を計算してからスクロールする。
- デフォルトのアンカー動作は止め、スムース移動に置き換えると体験が綺麗。
