jQuery / メソッド / .scrollTop() - 縦スクロール位置を取得・設定する
jQueryの.scrollTop()は最初の対象の現在の縦スクロール位置を数値で取得し、.scrollTop(120)は全対象に設定します。ページ全体は$(window)、内部スクロールは該当要素を選びます。文書内で要素が置かれた座標とは別です。
対象とスクロール位置を区別する
.scrollTop()の仕様は上側に隠れた内容の量をCSSピクセルで表します。通常の上から下の配置では先頭0、下ほど大きくなります。スクロールバーの画面座標やCSS topではありません。
| 操作 | 対象と呼び出し | 必要条件 |
|---|---|---|
| ページ位置取得 | $(window).scrollTop() | 文書が表示領域より長い |
| ボックス内120pxへ | $("#box").scrollTop(120) | 高さ制限と溢れる内容 |
| 先頭へ | 対象.scrollTop(0) | 実際のスクロール対象 |
ネイティブのElement.scrollTopとwindow.scrollYでも取得できます。例は両対象をjQueryの同じメソッドで比較します。読み取りだけでは移動しません。
ページと内部ボックスを比較する完全な例
全コードをUTF-8のscroll-demo.htmlとして保存しブラウザーで開きます。コンテンツ配信ネットワーク(CDN)の公式jQueryファイル4.0.0を読むインターネットが必要で、インストールは不要です。位置変更、範囲超過、初期化とConsole例をWindows Edgeと3.7.1・4.0.0で実行しました。
文書は最小2000px高、ボックスは文書top 500pxです。100pxの6行で内容600px、内部表示高160pxなので最大移動は600 - 160 = 440pxです。境界線は内部高に含めません。直接比較のためscroll-behavior:autoです。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Separate page and element scroll positions</title>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<style>
html { scroll-behavior: auto; }
body { margin: 0; min-height: 2000px; font: 16px/1.6 sans-serif; }
#controls { position: fixed; top: 0; left: 0; right: 0; z-index: 2; background: #fff; padding: 12px; max-height: 42vh; overflow: auto; }
button { font: inherit; margin: 3px; }
pre { white-space: pre-wrap; overflow-wrap: anywhere; }
#box { position: absolute; top: 500px; left: 20px; right: 20px; max-width: 600px; height: 160px; overflow-y: auto; border: 2px solid teal; scroll-behavior: auto; }
.row { height: 100px; box-sizing: border-box; padding: 12px; border-bottom: 1px solid #abc; background: #edf9f6; }
</style>
</head>
<body>
<div id="controls">
<strong>Page and box scrolling</strong>
<button type="button" id="box120">Box to 120</button>
<button type="button" id="bottom">Box to bottom</button>
<button type="button" id="page300">Page to 300</button>
<button type="button" id="reset">Reset both</button>
<pre id="result" aria-live="polite"></pre>
</div>
<div id="box" tabindex="0" aria-label="Scrollable example rows">
<div class="row">Alpha</div><div class="row">Beta</div><div class="row">Gamma</div><div class="row">Delta</div><div class="row">Epsilon</div><div class="row">Zeta</div>
</div>
<script>
$(function () {
const $box = $("#box");
function report() {
const node = $box.get(0);
const top = $box.scrollTop();
const max = Math.max(0, node.scrollHeight - node.clientHeight);
const bottom = max > 0 && Math.abs(max - top) <= 1;
$("#result").text(`window=${$(window).scrollTop()}\nbox=${top}\nbox max=${max}\nat bottom=${bottom}`);
}
$("#box120").on("click", function () { $box.scrollTop(120); report(); });
$("#bottom").on("click", function () { $box.scrollTop(1000000); report(); });
$("#page300").on("click", function () { $(window).scrollTop(300); report(); });
$("#reset").on("click", function () { $box.scrollTop(0); $(window).scrollTop(0); report(); });
$box.on("scroll.scrollLesson", report);
$(window).on("scroll.scrollLesson resize.scrollLesson", report);
report();
});
</script>
</body>
</html>
両方先頭の初期結果です。表示領域が2000pxより高く文書が溢れなければ、ページ移動確認のため高さを小さくします。
window=0
box=0
box max=440
at bottom=false
- Box to 120はbox=120、window=0のままです。Alphaの一部が上に隠れ次の行が見えます。
- Page to 300はwindow=300、box=120です。画面内の箱の移動と箱内内容の移動は別です。
- Box to bottomは1000000を要求しても最大440となり、at bottom=trueです。
- 箱内でスクロールやキーボード操作をすると該当scrollイベントで更新します。固定操作部で両値を確認できます。
- Reset bothは両対象を個別に0へ戻します。繰り返しても初期結果です。
実際にスクロールする要素へ直接登録します。windowのscrollだけで内部ボックスも扱えるとは仮定しません。report()は両位置と現在の最大値を読み直します。
最大値・末尾判定と複数要素
通常の縦ボックスの最大値はMath.max(0, scrollHeight - clientHeight)です。scrollHeightは内容高、clientHeightは内部表示高です。例は最大値が正かつ現在との差1px以内で末尾とし、厳密一致でなく小数の誤差を許容します。
溢れない箱は要求しても0の場合があります。例はこの場合at bottom=falseにしますが、短い箱を末尾扱いするかはUIの目的で決めます。画像・フォント・サイズ変更で内容高や最大値も変わります。
同じページの開発者ツールConsoleで次を実行します。一時ボックス二つへ異なる位置を設定し、集合の取得は最初だけ、80の設定は両方になることを確認後に削除します。
const $holder = $("<div>").appendTo("body");
const $boxes = $("<div></div><div></div>").css({ height: 40, overflowY: "auto" }).appendTo($holder);
$boxes.each(function () { $(this).append($("<div>").css("height", 200)); });
$boxes.eq(0).scrollTop(40);
$boxes.eq(1).scrollTop(100);
console.log(`first getter=${$boxes.scrollTop()}`);
$boxes.scrollTop(80);
console.log(`all=${$boxes.map(function () { return $(this).scrollTop(); }).get().join(",")}`);
console.log(`empty getter=${typeof $().scrollTop()}`);
$holder.remove();
first getter=40
all=80,80
empty getter=undefined
空の取得はundefinedです。正常位置0と区別し、存在するはずなら.length、実際のスクロール要素、DOM(Document Object Model、文書オブジェクトモデル)の準備を確認します。
移動しない・値が違うとき
overflow-y:autoだけでも内容に合わせ高くなる箱にはスクロールが不要です。高さ・最大高さと実scrollHeight/clientHeightを確認します。祖先がスクロールしているのに子を選ぶと子の値は0のままの場合があります。
ページはwindowを対象にして内部箱と区別します。数値設定自体はjQueryの時間付き効果を要求しません。外部の滑らかなスクロールCSSや効果があれば実行時点も確認し、途中値を最終と断定しません。
常に整数・非負とは一般化しません。MDNは小数、column-reverseなど逆配置の負数、Safariの境界外反応を説明しています。確認した0〜440は通常配置の例とEdgeでの結果です。他の構造では方向とブラウザー動作を先に確認します。




