← Back to jQuery Course | Chapter 6: CSS & Dimensions | Lesson 6 of 6

Tracking Scroll Positions

scrollTop() can read how far the page has been scrolled vertically.
Syntax
javascript
$(window).scrollTop();
$(selector).scrollTop(value);
$(selector).scrollLeft(value);

Reading Window Scroll

Calling $(window).scrollTop() with no argument returns the number of pixels the whole page has been scrolled down from the top. This is the basis for features like showing a 'back to top' button once the user scrolls past a certain point.

Example: Reading Window Scroll

javascript
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    body { font-family: sans-serif; padding: 12px; }
    button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
    button.secondary, #resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
    input[type=text] { padding: 6px 8px; margin: 0 6px 8px 0; border: 1px solid #888; border-radius: 4px; font: 14px sans-serif; }
    .stage { border: 2px dashed #888; border-radius: 4px; padding: 10px; margin: 8px 0; min-height: 40px; background: #fafafa; }
    .stage::before { content: attr(data-label); display: block; font-size: 12px; color: #666; margin-bottom: 6px; }
    .item { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .fresh { background: #ffe066 !important; border-color: #d4a600 !important; }
    .done { text-decoration: line-through; color: #a33; }
    ul.stage { padding-left: 32px; }
    ul.stage:empty::after { content: "(empty)"; color: #999; }
    ul.stage > li { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .box { border: 2px solid #4a7fb5; background: #f3f8fd; border-radius: 4px; padding: 8px 10px; margin: 8px 0; min-height: 54px; }
    .box .label { display: block; font-weight: bold; margin-bottom: 6px; color: #2c6aa0; }
    #output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; white-space:pre-wrap; }
    #output:empty::before { content: "Output appears here"; color: #888; }
    #panel { position: relative; height: 150px; overflow: auto; border: 2px solid navy; background: #fff; margin: 8px 0; }
    #tall { position: relative; height: 600px; background: repeating-linear-gradient(180deg, #eaf2fb 0 100px, #d6e6f7 100px 200px); }
    #tall .tick { position: absolute; left: 0; width: 100%; border-top: 1px solid #4a7fb5; font-size: 12px; color: #2c6aa0; padding-left: 6px; }
    #target { position: absolute; top: 340px; left: 10px; right: 10px; padding: 8px 10px; background: gold; border: 2px solid #b8860b; font-weight: bold; }
    .hint { font-size: 13px; color: #555; margin: 4px 0; }
  </style>
</head>
<body>
  <button id="runBtn">Read scrollTop()</button><button id="resetBtn" class="secondary">Reset</button>
  <p class="hint">Scroll inside the box first, then press the button.</p>
  <div id="panel"><div id="tall"><div class="tick" style="top:0px">0 px</div><div class="tick" style="top:100px">100 px</div><div class="tick" style="top:200px">200 px</div><div class="tick" style="top:300px">300 px</div><div class="tick" style="top:400px">400 px</div><div class="tick" style="top:500px">500 px</div></div></div>
  <div id="output"></div>
  <script>
    function pos() { return "#panel scrollTop() = " + $("#panel").scrollTop() + "  (max " + ($("#panel")[0].scrollHeight - $("#panel").innerHeight()) + ")"; }
    $("#runBtn").click(function () {
      $("#output").text(pos() + "\n$(window).scrollTop() = " + $(window).scrollTop() + "  (the whole page)");
    });
    $("#resetBtn").click(function () {
      $("#panel").scrollTop(0);
      $("#output").text("");
    });
  </script>
</body>
</html>

Reading Element Scroll

scrollTop() also works on individual scrollable elements, not just the window, returning how far that specific element's content has scrolled. This is useful for a scrollable panel or chat box that has its own independent scroll position.

Example: Reading Element Scroll

javascript
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    body { font-family: sans-serif; padding: 12px; }
    button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
    button.secondary, #resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
    input[type=text] { padding: 6px 8px; margin: 0 6px 8px 0; border: 1px solid #888; border-radius: 4px; font: 14px sans-serif; }
    .stage { border: 2px dashed #888; border-radius: 4px; padding: 10px; margin: 8px 0; min-height: 40px; background: #fafafa; }
    .stage::before { content: attr(data-label); display: block; font-size: 12px; color: #666; margin-bottom: 6px; }
    .item { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .fresh { background: #ffe066 !important; border-color: #d4a600 !important; }
    .done { text-decoration: line-through; color: #a33; }
    ul.stage { padding-left: 32px; }
    ul.stage:empty::after { content: "(empty)"; color: #999; }
    ul.stage > li { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .box { border: 2px solid #4a7fb5; background: #f3f8fd; border-radius: 4px; padding: 8px 10px; margin: 8px 0; min-height: 54px; }
    .box .label { display: block; font-weight: bold; margin-bottom: 6px; color: #2c6aa0; }
    #output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; white-space:pre-wrap; }
    #output:empty::before { content: "Output appears here"; color: #888; }
    #panel { position: relative; height: 150px; overflow: auto; border: 2px solid navy; background: #fff; margin: 8px 0; }
    #tall { position: relative; height: 600px; background: repeating-linear-gradient(180deg, #eaf2fb 0 100px, #d6e6f7 100px 200px); }
    #tall .tick { position: absolute; left: 0; width: 100%; border-top: 1px solid #4a7fb5; font-size: 12px; color: #2c6aa0; padding-left: 6px; }
    #target { position: absolute; top: 340px; left: 10px; right: 10px; padding: 8px 10px; background: gold; border: 2px solid #b8860b; font-weight: bold; }
    .hint { font-size: 13px; color: #555; margin: 4px 0; }
  </style>
</head>
<body>
  <button id="runBtn">Read #panel scrollTop()</button><button id="resetBtn" class="secondary">Reset</button>
  <p class="hint">Scroll the panel with your mouse or scrollbar, then press the button.</p>
  <div id="panel"><div id="tall"><div class="tick" style="top:0px">0 px</div><div class="tick" style="top:100px">100 px</div><div class="tick" style="top:200px">200 px</div><div class="tick" style="top:300px">300 px</div><div class="tick" style="top:400px">400 px</div><div class="tick" style="top:500px">500 px</div></div></div>
  <div id="output"></div>
  <script>
    function pos() { return "#panel scrollTop() = " + $("#panel").scrollTop() + "  (max " + ($("#panel")[0].scrollHeight - $("#panel").innerHeight()) + ")"; }
    $("#runBtn").click(function () { $("#output").text(pos()); });
    $("#resetBtn").click(function () {
      $("#panel").scrollTop(0);
      $("#output").text("");
    });
  </script>
</body>
</html>

Setting Scroll Position

scrollTop() can set the vertical scroll position by passing a pixel value, immediately moving the page or element to that position. Combined with jQuery's animate(), this is also how you build a smooth scrolling effect.

Example: Setting Scroll Position

javascript
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    body { font-family: sans-serif; padding: 12px; }
    button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
    button.secondary, #resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
    input[type=text] { padding: 6px 8px; margin: 0 6px 8px 0; border: 1px solid #888; border-radius: 4px; font: 14px sans-serif; }
    .stage { border: 2px dashed #888; border-radius: 4px; padding: 10px; margin: 8px 0; min-height: 40px; background: #fafafa; }
    .stage::before { content: attr(data-label); display: block; font-size: 12px; color: #666; margin-bottom: 6px; }
    .item { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .fresh { background: #ffe066 !important; border-color: #d4a600 !important; }
    .done { text-decoration: line-through; color: #a33; }
    ul.stage { padding-left: 32px; }
    ul.stage:empty::after { content: "(empty)"; color: #999; }
    ul.stage > li { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .box { border: 2px solid #4a7fb5; background: #f3f8fd; border-radius: 4px; padding: 8px 10px; margin: 8px 0; min-height: 54px; }
    .box .label { display: block; font-weight: bold; margin-bottom: 6px; color: #2c6aa0; }
    #output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; white-space:pre-wrap; }
    #output:empty::before { content: "Output appears here"; color: #888; }
    #panel { position: relative; height: 150px; overflow: auto; border: 2px solid navy; background: #fff; margin: 8px 0; }
    #tall { position: relative; height: 600px; background: repeating-linear-gradient(180deg, #eaf2fb 0 100px, #d6e6f7 100px 200px); }
    #tall .tick { position: absolute; left: 0; width: 100%; border-top: 1px solid #4a7fb5; font-size: 12px; color: #2c6aa0; padding-left: 6px; }
    #target { position: absolute; top: 340px; left: 10px; right: 10px; padding: 8px 10px; background: gold; border: 2px solid #b8860b; font-weight: bold; }
    .hint { font-size: 13px; color: #555; margin: 4px 0; }
  </style>
</head>
<body>
  <button id="runBtn">scrollTop(300)</button><button id="topBtn">scrollTop(0)</button><button id="bottomBtn">Scroll to bottom</button><button id="resetBtn" class="secondary">Reset</button>
  <div id="panel"><div id="tall"><div class="tick" style="top:0px">0 px</div><div class="tick" style="top:100px">100 px</div><div class="tick" style="top:200px">200 px</div><div class="tick" style="top:300px">300 px</div><div class="tick" style="top:400px">400 px</div><div class="tick" style="top:500px">500 px</div></div></div>
  <div id="output"></div>
  <script>
    function pos() { return "#panel scrollTop() = " + $("#panel").scrollTop() + "  (max " + ($("#panel")[0].scrollHeight - $("#panel").innerHeight()) + ")"; }
    $("#runBtn").click(function () { $("#panel").scrollTop(300); $("#output").text("scrollTop(300) -> " + pos()); });
    $("#topBtn").click(function () { $("#panel").scrollTop(0); $("#output").text("scrollTop(0) -> " + pos()); });
    $("#bottomBtn").click(function () {
      $("#panel").scrollTop($("#panel")[0].scrollHeight);
      $("#output").text("scrollTop(scrollHeight) -> " + pos());
    });
    $("#resetBtn").click(function () { $("#panel").scrollTop(0); $("#output").text(""); });
  </script>
</body>
</html>

Example: Scroll to Top and Bottom Buttons

javascript
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    body { font-family: sans-serif; padding: 12px; }
    button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
    button.secondary, #resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
    input[type=text] { padding: 6px 8px; margin: 0 6px 8px 0; border: 1px solid #888; border-radius: 4px; font: 14px sans-serif; }
    .stage { border: 2px dashed #888; border-radius: 4px; padding: 10px; margin: 8px 0; min-height: 40px; background: #fafafa; }
    .stage::before { content: attr(data-label); display: block; font-size: 12px; color: #666; margin-bottom: 6px; }
    .item { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .fresh { background: #ffe066 !important; border-color: #d4a600 !important; }
    .done { text-decoration: line-through; color: #a33; }
    ul.stage { padding-left: 32px; }
    ul.stage:empty::after { content: "(empty)"; color: #999; }
    ul.stage > li { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .box { border: 2px solid #4a7fb5; background: #f3f8fd; border-radius: 4px; padding: 8px 10px; margin: 8px 0; min-height: 54px; }
    .box .label { display: block; font-weight: bold; margin-bottom: 6px; color: #2c6aa0; }
    #output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; white-space:pre-wrap; }
    #output:empty::before { content: "Output appears here"; color: #888; }
    #panel { position: relative; height: 150px; overflow: auto; border: 2px solid navy; background: #fff; margin: 8px 0; }
    #tall { position: relative; height: 600px; background: repeating-linear-gradient(180deg, #eaf2fb 0 100px, #d6e6f7 100px 200px); }
    #tall .tick { position: absolute; left: 0; width: 100%; border-top: 1px solid #4a7fb5; font-size: 12px; color: #2c6aa0; padding-left: 6px; }
    #target { position: absolute; top: 340px; left: 10px; right: 10px; padding: 8px 10px; background: gold; border: 2px solid #b8860b; font-weight: bold; }
    .hint { font-size: 13px; color: #555; margin: 4px 0; }
  </style>
</head>
<body>
  <button id="runBtn">Scroll to Top</button><button id="bottomBtn">Scroll to Bottom</button><button id="resetBtn" class="secondary">Reset</button>
  <p class="hint">Scroll down inside the panel, then use the buttons.</p>
  <div id="panel"><div id="tall"><div class="tick" style="top:0px">0 px</div><div class="tick" style="top:100px">100 px</div><div class="tick" style="top:200px">200 px</div><div class="tick" style="top:300px">300 px</div><div class="tick" style="top:400px">400 px</div><div class="tick" style="top:500px">500 px</div></div></div>
  <div id="output"></div>
  <script>
    function pos() { return "#panel scrollTop() = " + $("#panel").scrollTop() + "  (max " + ($("#panel")[0].scrollHeight - $("#panel").innerHeight()) + ")"; }
    $("#panel").on("scroll", function () { $("#output").text(pos()); });
    $("#runBtn").click(function () {
      $("#panel").stop(true).animate({scrollTop: 0}, 400);
    });
    $("#bottomBtn").click(function () {
      $("#panel").stop(true).animate({scrollTop: $("#panel")[0].scrollHeight}, 400);
    });
    $("#resetBtn").click(function () { $("#panel").stop(true).scrollTop(0); });
    $("#output").text(pos());
  </script>
</body>
</html>

Scroll Events

The scroll event fires whenever a scrollable area -- the window or an individual element -- changes position, letting you react as the user scrolls. Because it can fire very frequently, scroll handlers are often throttled to avoid doing expensive work on every pixel of movement.

Example: Scroll Events

javascript
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    body { font-family: sans-serif; padding: 12px; }
    button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
    button.secondary, #resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
    input[type=text] { padding: 6px 8px; margin: 0 6px 8px 0; border: 1px solid #888; border-radius: 4px; font: 14px sans-serif; }
    .stage { border: 2px dashed #888; border-radius: 4px; padding: 10px; margin: 8px 0; min-height: 40px; background: #fafafa; }
    .stage::before { content: attr(data-label); display: block; font-size: 12px; color: #666; margin-bottom: 6px; }
    .item { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .fresh { background: #ffe066 !important; border-color: #d4a600 !important; }
    .done { text-decoration: line-through; color: #a33; }
    ul.stage { padding-left: 32px; }
    ul.stage:empty::after { content: "(empty)"; color: #999; }
    ul.stage > li { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .box { border: 2px solid #4a7fb5; background: #f3f8fd; border-radius: 4px; padding: 8px 10px; margin: 8px 0; min-height: 54px; }
    .box .label { display: block; font-weight: bold; margin-bottom: 6px; color: #2c6aa0; }
    #output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; white-space:pre-wrap; }
    #output:empty::before { content: "Output appears here"; color: #888; }
    #panel { position: relative; height: 150px; overflow: auto; border: 2px solid navy; background: #fff; margin: 8px 0; }
    #tall { position: relative; height: 600px; background: repeating-linear-gradient(180deg, #eaf2fb 0 100px, #d6e6f7 100px 200px); }
    #tall .tick { position: absolute; left: 0; width: 100%; border-top: 1px solid #4a7fb5; font-size: 12px; color: #2c6aa0; padding-left: 6px; }
    #target { position: absolute; top: 340px; left: 10px; right: 10px; padding: 8px 10px; background: gold; border: 2px solid #b8860b; font-weight: bold; }
    .hint { font-size: 13px; color: #555; margin: 4px 0; }
  </style>
</head>
<body>
  <button id="resetBtn">Scroll back to top</button>
  <p class="hint">Scroll the panel: the scroll event updates the output below.</p>
  <div id="panel"><div id="tall"><div class="tick" style="top:0px">0 px</div><div class="tick" style="top:100px">100 px</div><div class="tick" style="top:200px">200 px</div><div class="tick" style="top:300px">300 px</div><div class="tick" style="top:400px">400 px</div><div class="tick" style="top:500px">500 px</div></div></div>
  <div id="output">Scroll the panel above...</div>
  <script>
    var count = 0;
    $("#panel").on("scroll", function () {
      count++;
      $("#output").text("scroll event #" + count + "\nscrollTop() = " + $(this).scrollTop());
    });
    $("#resetBtn").click(function () { $("#panel").scrollTop(0); });
  </script>
</body>
</html>

Scroll to an Element

You can combine an element's offset() coordinates with scrollTop() to move the page so that a specific element comes into view. This is the basic technique behind 'jump to section' links and smooth-scrolling navigation menus.

Example: Scroll to an Element

javascript
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <style>
    body { font-family: sans-serif; padding: 12px; }
    button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
    button.secondary, #resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
    input[type=text] { padding: 6px 8px; margin: 0 6px 8px 0; border: 1px solid #888; border-radius: 4px; font: 14px sans-serif; }
    .stage { border: 2px dashed #888; border-radius: 4px; padding: 10px; margin: 8px 0; min-height: 40px; background: #fafafa; }
    .stage::before { content: attr(data-label); display: block; font-size: 12px; color: #666; margin-bottom: 6px; }
    .item { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .fresh { background: #ffe066 !important; border-color: #d4a600 !important; }
    .done { text-decoration: line-through; color: #a33; }
    ul.stage { padding-left: 32px; }
    ul.stage:empty::after { content: "(empty)"; color: #999; }
    ul.stage > li { border: 1px solid #4a7fb5; background: #eaf2fb; padding: 6px 10px; margin: 4px 0; border-radius: 4px; }
    .box { border: 2px solid #4a7fb5; background: #f3f8fd; border-radius: 4px; padding: 8px 10px; margin: 8px 0; min-height: 54px; }
    .box .label { display: block; font-weight: bold; margin-bottom: 6px; color: #2c6aa0; }
    #output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; white-space:pre-wrap; }
    #output:empty::before { content: "Output appears here"; color: #888; }
    #panel { position: relative; height: 150px; overflow: auto; border: 2px solid navy; background: #fff; margin: 8px 0; }
    #tall { position: relative; height: 600px; background: repeating-linear-gradient(180deg, #eaf2fb 0 100px, #d6e6f7 100px 200px); }
    #tall .tick { position: absolute; left: 0; width: 100%; border-top: 1px solid #4a7fb5; font-size: 12px; color: #2c6aa0; padding-left: 6px; }
    #target { position: absolute; top: 340px; left: 10px; right: 10px; padding: 8px 10px; background: gold; border: 2px solid #b8860b; font-weight: bold; }
    .hint { font-size: 13px; color: #555; margin: 4px 0; }
  </style>
</head>
<body>
  <button id="runBtn">Jump to target</button><button id="animBtn">Animate to target</button><button id="resetBtn" class="secondary">Reset</button>
  <div id="panel"><div id="tall"><div class="tick" style="top:0px">0 px</div><div class="tick" style="top:100px">100 px</div><div class="tick" style="top:200px">200 px</div><div class="tick" style="top:300px">300 px</div><div class="tick" style="top:400px">400 px</div><div class="tick" style="top:500px">500 px</div><div id="target">Target section</div></div></div>
  <div id="output"></div>
  <script>
    function targetTop() { return $("#target").offset().top - $("#tall").offset().top; }
    $("#runBtn").click(function () {
      var top = targetTop();
      $("#panel").scrollTop(top);
      $("#output").text("target is " + top + "px from the top of the content\nscrollTop() is now " + $("#panel").scrollTop());
    });
    $("#animBtn").click(function () {
      var top = targetTop();
      $("#output").text("animating to " + top + "px...");
      $("#panel").stop(true).animate({scrollTop: top}, 500, function () {
        $("#output").text("arrived: scrollTop() = " + $("#panel").scrollTop());
      });
    });
    $("#resetBtn").click(function () { $("#panel").stop(true).scrollTop(0); $("#output").text(""); });
  </script>
</body>
</html>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Calling $("#panel").scrollTop() on an element that is not scrollable, which always returns 0 because it needs overflow:auto or scroll.
  2. Reading scrollTop() once and expecting it to update, when it must be read again inside a scroll event handler.
  3. Using $("body").scrollTop() for the page in some browsers, when $(window).scrollTop() is the dependable form.
Chapter Summary
  • jQuery gets and sets CSS rules and manages classes on elements.
  • It reads element width, height, and inner and outer dimensions.
  • It also reports element coordinates and tracks scroll positions.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.