jQuery / Método / .scrollTop() - Ler ou definir a posição vertical

No jQuery, .scrollTop() lê a posição vertical atual do primeiro alvo e .scrollTop(120) define em todos. Selecione $(window) para a página ou o elemento para um contêiner interno. Isso não lê a posição do elemento no documento.

Escolher o alvo da rolagem

A API de .scrollTop() mede conteúdo oculto acima em pixels CSS. No fluxo normal de cima para baixo, zero é o início e o valor aumenta para baixo. Não é a coordenada visual do indicador da barra nem CSS top.

Tarefa Alvo e chamada Condição
Ler a página $(window).scrollTop() Documento mais alto que a área visível
Mover caixa para 120px $("#box").scrollTop(120) Altura limitada e conteúdo excedente
Voltar ao início alvo.scrollTop(0) Alvo que realmente rola

As leituras nativas são Element.scrollTop e window.scrollY. Aqui o jQuery usa um método para ambos. Ler não move a visualização.

Exemplo completo de página e caixa

Salve todo o código em UTF-8 como scroll-demo.html e abra no navegador. É preciso Internet para o arquivo oficial do jQuery 4.0.0 da rede de distribuição de conteúdo (CDN), sem instalação. Posições, pedidos excessivos, restauração e Console foram executados com 3.7.1 e 4.0.0 no Edge para Windows.

O documento tem pelo menos 2000px, e a caixa fica em top 500px. Seis linhas de 100px produzem 600px de conteúdo com 160px internos visíveis: máximo 600 - 160 = 440px. Bordas ficam fora dessa altura. scroll-behavior:auto permite comparação direta.

<!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>

A saída pressupõe ambos no início. Se a área visível superar 2000px e a página não transbordar, reduza sua altura para testar.

window=0
box=0
box max=440
at bottom=false
  1. Box to 120 dá box=120 e mantém window=0. Parte de Alpha fica oculta acima.
  2. Page to 300 dá window=300, box=120. Mover a caixa na tela difere de mover seu conteúdo.
  3. Box to bottom pede 1000000, mas esta caixa normal limita a 440. at bottom vira true.
  4. Role diretamente ou use o teclado dentro da caixa para atualizar seu evento scroll. Os controles fixos mantêm as leituras acessíveis.
  5. Reset both retorna caixa e janela separadamente a zero, mesmo ao repetir.

Registre scroll diretamente no elemento que rola. window scroll não trata automaticamente a caixa interna. report() lê ambas as posições e recalcula o máximo.

Máximo, final e vários elementos

Em uma caixa vertical normal, o máximo é Math.max(0, scrollHeight - clientHeight). scrollHeight mede conteúdo e clientHeight o interior visível. O exemplo exige máximo positivo e diferença de até 1px para indicar o final, sem igualdade exata diante de possíveis frações.

Sem transbordamento, o pedido pode manter zero. Aqui at bottom fica false; considerar uma caixa curta já no final depende da interface. Imagens, fontes e dimensões podem mudar altura e máximo.

Execute isto no Console da mesma página. Duas caixas temporárias recebem posições diferentes. Consultar a coleção lê só a primeira; definir 80 altera ambas. A área temporária é removida depois.

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

Uma seleção vazia retorna undefined. Zero é posição válida, não ausência de alvo. Confira .length, o elemento que rola e a preparação do modelo de objetos do documento (DOM).

Investigar falta de movimento ou valores diferentes

overflow-y:auto não basta se a caixa cresce com o conteúdo. Confira altura ou altura máxima e scrollHeight/clientHeight. Se um ancestral rola, mas você seleciona o filho, este pode continuar em zero.

Use window para diferenciar página e contêineres. Definir um número não pede sozinho uma animação temporizada do jQuery. CSS de rolagem suave ou outros efeitos podem mudar o tempo: não trate leitura intermediária como resultado final.

Nem todos os valores são inteiros ou não negativos. A MDN descreve frações, valores negativos com column-reverse e ultrapassagem dos limites no Safari. O intervalo verificado 0–440 pertence a esta caixa normal no Edge. Em outros layouts, confira direção e comportamento do navegador.