jQuery / Plugin / jQuery Smooth Scroll
jQuery Smooth Scrollはhref="#beta"のような同じページ内のリンク移動をアニメーションにするプラグインです。リンクを選んで.smoothScroll()を呼び、speedで時間、offsetで到着位置を調整します。到着先のフォーカスと動きの軽減も扱うと、表示以外の操作も続けやすくなります。
対象と必要なファイル
使うのはkswedbergのjquery-smooth-scrollで、同名に近いホイール制御ライブラリーとは別です。href="#beta"に対応する一意のid="beta"を同じ文書内に用意します。
CDNのプラグイン2.2.0と完全版jQuery4.0.0を固定します。jQuery、プラグイン、初期化の順で、必要な効果がないslimは使いません。同じプラグインをWindows Edgeで4.0.0・3.7.1それぞれと実行しました。テーマや別プラグインを含む全環境の互換性ではありません。
対象はメニュー内の.js-scroll二リンクだけです。Native jumpと本文のリンクは通常動作を残し比較できます。サイトの全aへ無差別に適用せず、ページ内案内という意図の明確な範囲に限定します。
余白とフォーカスを含む完全な例
UTF-8のsmooth-scroll-demo.htmlとして保存し開きます。サーバーやビルドは不要で、ネット接続から二つのスクリプトを読みます。各節と末尾に十分な空間を取り、到着位置を観察できます。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Same-page smooth scrolling</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-smooth-scroll/2.2.0/jquery.smooth-scroll.min.js"></script>
<style>
:root { --anchor-gap: 100px; }
html { scroll-behavior: auto; }
body { font: 16px/1.6 sans-serif; margin: 20px; padding-top: var(--anchor-gap); }
#menu { position: fixed; top: 0; left: 0; right: 0; padding: 12px; background: #e6f4f1; z-index: 10; }
#menu a, #menu button { display: inline-block; margin: 4px 8px; font: inherit; }
section { min-height: 700px; max-width: 700px; }
h2 { scroll-margin-top: var(--anchor-gap); }
h2:focus { outline: 3px solid teal; }
footer { min-height: 100vh; }
</style>
</head>
<body>
<nav id="menu" aria-label="Sections">
<a class="js-scroll" href="#alpha">Alpha</a>
<a class="js-scroll" href="#beta">Beta</a>
<a href="#native">Native jump</a>
<button type="button" id="reset">Reset</button>
<span id="status" role="status">Native links available.</span>
</nav>
<h1>Explore the sections</h1>
<section><h2 id="alpha" tabindex="-1">Alpha</h2><p>First destination. Text remains available without JavaScript.</p></section>
<section><h2 id="beta" tabindex="-1">Beta</h2><p>Second destination. Tab can continue to <a href="#native">the next destination</a>.</p></section>
<section><h2 id="native" tabindex="-1">Native destination</h2><p>This menu link is not enhanced by the plugin.</p></section>
<footer>Enough space to align the last heading below the menu.</footer>
<script>
jQuery(function ($) {
if (typeof $.fn.smoothScroll !== "function") return;
const $menu = $("#menu"), $status = $("#status"), duration = 600;
function gap() {
const value = $menu.outerHeight() + 12;
document.documentElement.style.setProperty("--anchor-gap", value + "px");
return value;
}
gap(); $(window).on("resize.demo", gap);
$("#menu a.js-scroll").smoothScroll({
speed: duration, easing: "swing", autoFocus: true,
beforeScroll: function (options) {
options.offset = -gap();
options.speed = window.matchMedia("(prefers-reduced-motion: reduce)").matches ? 0 : duration;
$status.text("Moving to " + options.scrollTarget);
},
afterScroll: function (options) {
history.replaceState(null, "", options.scrollTarget);
$status.text("Arrived at " + options.scrollTarget);
}
});
$("#reset").on("click", function () {
$("html, body").stop(true, false); window.scrollTo(0, 0);
history.replaceState(null, "", location.pathname + location.search);
$status.text("Ready; enhanced links: 2.");
});
$status.text("Ready; enhanced links: 2.");
});
</script>
</body>
</html>
準備後は次の表示です。JavaScriptを無効にするとNative links available.が残り、通常のハッシュリンクとして動きます。
Ready; enhanced links: 2.
- Betaを選ぶと約600msで移動しArrived at #betaになります。見出しはメニューの12px下に止まります。
- Resetで先頭とハッシュなしURLへ戻します。AlphaかBetaへキーボードでフォーカスしEnterを押します。
- 到着見出しには輪郭が出ます。Beta後にTabで本文のリンクへ続けます。
- Native jumpはプラグインを通らず、到着状態の表示も更新しません。
- 動きの軽減をreduceにすると時間0で同じ目的地と完了処理になります。
- 幅を変えてメニューが折り返しても見出しが隠れないことを確認し、Resetで再比較します。
tabindex="-1"は通常のTab順へ追加せずプログラムから見出しをフォーカス可能にします。autoFocus=trueで到着後のキーボード位置も移し、メニューへ置き去りにしません。
時間・位置・URLの方針
speedはこの例ではミリ秒の所要時間で、小さいほど同距離を速く移動します。同じ目的地でduration定数を600から1200へ変えて比較し600へ戻します。easingは時間を固定してswingとlinearを比較します。他の名前は対応する拡張が必要です。
offsetは目標座標に加える値です。上に空間を作るためメニュー実高さと12pxの合計を負数にします。beforeScrollで測り直すので折返しを反映します。正数ではさらに下へ進み、固定メニューにタイトルが隠れることがあります。
通常リンクにはscroll-margin-top、プラグインには数値offsetを使います。CSS指定がプラグインの座標計算を代行するとは考えず、両方確認します。
プラグインは既定でリンクの通常動作を止めます。この例は完了後にhistory.replaceState()でハッシュを変更します。現在の履歴を置換するため目的地ごとに戻る履歴は増えず、hashchangeでの案内も実装していません。戻る・進むが必要なアプリは別の履歴設計が必要です。
Resetは進行中と待機中の効果を止め、位置・ハッシュ・状態を復元します。連続した目的地変更も確認しましたが、ホイールを含む全入力での中断を実装したものではありません。
CSSの代替と診断
単純なアンカーならscroll-behaviorでも実現できます。次は併用ではなく代替です。外部二スクリプトと初期化、Resetボタンと状態表示を削除し、既存のhtmlのauto規則を置換します。見出しのscroll-margin-topは維持し、固定メニュー高さに合う余白を指定します。
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
}
ブラウザーの標準リンク・履歴を使い、プラグインのミリ秒指定やコールバックはありません。メディアクエリーで動きを減らします。逆にプラグイン例はCSSをautoにして二方式を競合させません。
smoothScroll is not a functionならNetworkの応答と順序を確認します。プラグイン後に別のjQueryを読むと拡張が失われることがあります。WordPressではテーマの登録依存関係を先に確認します。
移動しなければidの欠落・重複、実際のhref、選択範囲を確認します。ずれはメニュー高、遅れて読み込む画像・フォント、末尾の余地を点検します。内側のスクロール領域ではscrollElementと座標基準を別に設定・検証します。




