Como rolar para o topo da página com JavaScript / jQuery?

159

Existe uma maneira de controlar a rolagem do navegador com JavaScript / jQuery?

Quando rolar a página até a metade do caminho e acionar uma recarga, desejo que a página seja empacotada até o topo, mas ela tenta encontrar a última posição de rolagem. Então eu fiz isso:

$('document').ready(function() {
   $(window).scrollTop(0);
});

Mas sem sorte.

EDIT :

Então, ambas as suas respostas funcionaram quando eu as ligo após o carregamento da página - Obrigado. No entanto, se eu fizer uma atualização na página, o navegador calculará e rolará para a sua antiga posição de rolagem APÓS o .readyevento (eu testei a função body onload () também).

Portanto, o acompanhamento é: existe uma maneira de impedir que o navegador role para a posição anterior ou para voltar ao topo depois que ele faz o que quer?

Yarin
fonte
1
O que acontece quando você faz isso em $ (window) .load ()?
Mpdadadio 18/11
2
@ MPD- Excelente ideia! ... mas tentei e o ajuste de rolagem ainda acontece depois disso. Obrigado pela dica, porém, na verdade, ajuda com outra pergunta minha: stackoverflow.com/questions/4210829/… . Se você quer responder, eu lhe darei alguns altos.
Yarin
@ Yarin Desculpe, você teve que esperar 9 anos por isso. Você precisa definir o history.scrollRestoration antes de tentar rolar. Veja minha resposta.
RayLoveless

Respostas:

17

Uau, estou com 9 anos de atraso para esta pergunta. Aqui está:

Adicione esse código à sua carga.

// This prevents the page from scrolling down to where it was previously.
if ('scrollRestoration' in history) {
    history.scrollRestoration = 'manual';
}
// This is needed if the user scrolls down during page load and you want to make sure the page is scrolled to the top once it's fully loaded. This has Cross-browser support.
window.scrollTo(0,0);

history.scrollSuporte ao navegador de restauração:

Chrome: suportado (desde 46)

Firefox: suportado (desde 46)

IE / Edge: não suportado (ainda ..)

Opera: suportado (desde 33)

Safari: suportado

Para o IE / Edge, se você quiser rolar novamente para o topo APÓS que ele se desloque automaticamente, isso funcionou para mim:

var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
var isEdge = /Edge/.test(navigator.userAgent);
if(isIE11 || isEdge) {
    setTimeout(function(){ window.scrollTo(0, 0); }, 300);  // adjust time according to your page. The better solution would be to possibly tie into some event and trigger once the autoscrolling goes to the top.
} 
RayLoveless
fonte
Obrigado @RayLoveless - infelizmente isso não é suportado pelos navegadores MS (porque é claro). Veja caniuse.com/#feat=mdn-api_history_scrollrestoration e developer.mozilla.org/de/docs/Web/API/…
Yarin
@ Yarin, bom ponto. Eu atualizei minha postagem. Isso responde à sua pergunta?
RayLoveless
312

Solução JavaScript pura entre navegadores:

document.body.scrollTop = document.documentElement.scrollTop = 0;
Niet, o Escuro Absol
fonte
3
Desde que você está usando jQuery, você pode tentar o seguinte:$(window).one("scroll",function() { /* the code from my answer here */ });
Niet o Absol escuro
Para que isso funcione em meus navegadores IE / Chrome / FF, devo combinar a resposta Niet Dark Absol e a resposta user113716 (usando o tempo limite).
Panini Luncher 11/11
Não funcionou no CentOS 6.7 usando o FF 45.1.0. Enrolei-o em um documento. Já só para ter certeza.
Brandon Elliott #
Só quero salientar que a partir de meu teste (em modernas / 2018 versões do Chrome incluído) que esta solução funciona de forma mais confiável
mattLummus
Isso não "impede que o navegador role para a posição anterior". Veja minha resposta.
RayLoveless
85

Você quase tem que - você precisa definir o scrollTopon body, não window:

$(function() {
   $('body').scrollTop(0);
});

EDITAR:

Talvez você possa adicionar uma âncora em branco ao topo da página:

$(function() {
   $('<a name="top"/>').insertBefore($('body').children().eq(0));
   window.location.hash = 'top';
});
Jacob Relkin
fonte
3
Tentei isso hoje e não funcionou no FF16. Usando JS puro, visto abaixo nesta página, em vez disso: document.body.scrollTop = document.documentElement.scrollTop = 0;
Gigi2m02
2
O código acima funcionará corretamente em navegadores modernos como FF, Chrome, mas não funcionará no IE8 e, abaixo, tente adicionar ambos, 'html','body'pois os navegadores modernos rolarão com base no corpo, mas o IE8 e abaixo só rolarão com 'html', 'body'
Rajesh
17

Existe uma maneira de impedir que o navegador role para a posição anterior ou para voltar ao topo depois que ele faz o que quer?

A seguinte solução jquery funciona para mim:

$(window).unload(function() {
    $('body').scrollTop(0);
});
Matt
fonte
sim rolagem para cima antes de a atualização
Morgan T.
Não é completamente um navegador cruzado, mas ainda funciona para a maioria. Quando acoplado com algumas das outras respostas este é um bom complemento
Brad Decker
16

Aqui está uma versão de rolagem animada em JavaScript pura para no-jQuery'ers: D

var stepTime = 20;
var docBody = document.body;
var focElem = document.documentElement;

var scrollAnimationStep = function (initPos, stepAmount) {
    var newPos = initPos - stepAmount > 0 ? initPos - stepAmount : 0;

    docBody.scrollTop = focElem.scrollTop = newPos;

    newPos && setTimeout(function () {
        scrollAnimationStep(newPos, stepAmount);
    }, stepTime);
}

var scrollTopAnimated = function (speed) {
    var topOffset = docBody.scrollTop || focElem.scrollTop;
    var stepAmount = topOffset;

    speed && (stepAmount = (topOffset * stepTime)/speed);

    scrollAnimationStep(topOffset, stepAmount);
};

E depois:

<button onclick="scrollTopAnimated(1000)">Scroll Top</button>
ulfryk
fonte
1
Legal. No entanto, eu preferiria em requestAnimationStepvez de setTimeout. Também não responde à pergunta do OP.
Quentin Roy
implementou isso no Angular. Funciona como um encanto. Obrigado
Ahmad
12

ATUALIZAR

Ir para o topo da página com um efeito de rolagem é um pouco mais fácil em javascript agora com:

https://developer.mozilla.org/en-US/docs/Web/API/Window/scroll

window.scroll({
 top: 0, 
 left: 0, 
 behavior: 'smooth' 
});

CUIDADO

Temos usado isso em nossos projetos mais recentes, mas acabei de verificar o documento do mozilla agora enquanto atualizava minha resposta e acredito que ele foi atualizado. Neste momento, o método é window.scroll(x-coord, y-coord)e não menciona ou mostrar exemplos que usam o objectparâmetro, onde você pode definir o behaviorque smooth. Eu apenas tentei o código e ele ainda funciona no chrome e firefox e o parâmetro do objeto ainda está na especificação .

Portanto, use-o com cuidado ou use este Polyfill . Além de rolagem ao topo, este polyfill também lida com outros métodos: window.scrollBy, element.scrollIntoView, etc.


RESPOSTA ANTIGA

Esta é a nossa javascriptimplementação de baunilha . Ele tem um efeito de alívio simples, para que o usuário não fique chocado depois de clicar no botão Início .

É muito pequeno e fica ainda menor quando reduzido. Os desenvolvedores que procuram uma alternativa ao método jquery, mas desejam os mesmos resultados, podem tentar isso.

JS

document.querySelector("#to-top").addEventListener("click", function(){

    var toTopInterval = setInterval(function(){

        var supportedScrollTop = document.body.scrollTop > 0 ? document.body : document.documentElement;

        if (supportedScrollTop.scrollTop > 0) {
            supportedScrollTop.scrollTop = supportedScrollTop.scrollTop - 50;
        }

        if (supportedScrollTop.scrollTop < 1) {
            clearInterval(toTopInterval);
        }

    }, 10);

},false);

HTML

<button id="to-top">To Top</button>

Felicidades!

Jo E.
fonte
8

Isso funciona para mim:

window.onload = function() {
    // short timeout
    setTimeout(function() {
        $(document.body).scrollTop(0);
    }, 15);
};

Usa um pequeno setTimeoutdentro do onloadpara dar ao navegador a chance de fazer a rolagem.

user113716
fonte
Para que isso funcione em meus navegadores IE / Chrome / FF, devo combinar a resposta Niet Dark Absol e a resposta user113716 (usando o tempo limite).
Panini Luncher 11/11
@ Panini: sua sugestão funciona para mim no Chrome / FF, mas não no IE11.
EML
8

Você pode usar com jQuery

jQuery(window).load(function(){

    jQuery("html,body").animate({scrollTop: 100}, 1000);

});
Chanderkesh Kumar
fonte
Isso é basicamente o que eu finalmente encontrei para trabalhar no CentOS 6.7 usando o FF 45.1.0. Minha versão ligeiramente diferente (envolvida em uma função de carregamento de janela) é: $ ("html, body"). Animate ({scrollTop: 0}, 1);
Brandon Elliott #
6

Use a seguinte função

window.scrollTo(xpos, ypos)

Aqui xpos é obrigatório. A coordenada para rolar, ao longo do eixo x (horizontal), em pixels

ypos também é necessário. A coordenada para rolar, ao longo do eixo y (vertical), em pixels

Shoaib Quraishi
fonte
5
$(function() {
    // the element inside of which we want to scroll
        var $elem = $('#content');

        // show the buttons
    $('#nav_up').fadeIn('slow');
    $('#nav_down').fadeIn('slow');  

        // whenever we scroll fade out both buttons
    $(window).bind('scrollstart', function(){
        $('#nav_up,#nav_down').stop().animate({'opacity':'0.2'});
    });
        // ... and whenever we stop scrolling fade in both buttons
    $(window).bind('scrollstop', function(){
        $('#nav_up,#nav_down').stop().animate({'opacity':'1'});
    });

        // clicking the "down" button will make the page scroll to the $elem's height
    $('#nav_down').click(
        function (e) {
            $('html, body').animate({scrollTop: $elem.height()}, 800);
        }
    );
        // clicking the "up" button will make the page scroll to the top of the page
    $('#nav_up').click(
        function (e) {
            $('html, body').animate({scrollTop: '0px'}, 800);
        }
    );
 });

Usa isto

Ekin Ertaç
fonte
Agradável! Funciona bem com animação!
Sakthivel
4

O código a seguir funciona no Firefox, Chrome e Safari , mas não foi possível testar isso no Internet Explorer. Alguém pode testá-lo e editar minha resposta ou comentar sobre ele?

$(document).scrollTop(0);
Grande cego
fonte
4

Minha solução Javascript pura (animada):

function gototop() {
    if (window.scrollY>0) {
        window.scrollTo(0,window.scrollY-20)
        setTimeout("gototop()",10)
    }
}

Explicação:

window.scrollY é uma variável mantida pelo navegador da quantidade de pixels da parte superior pela qual a janela foi rolada.

window.scrollTo(x,y) é uma função que rola na janela uma quantidade específica de pixels no eixo xe no eixo y.

Assim, window.scrollTo(0,window.scrollY-20)move a página 20 pixels para o topo.

Ele setTimeoutchama a função novamente em 10 milissegundos para que possamos movê-la mais 20 pixels (animados), e a ifinstrução verifica se ainda precisamos rolar.

Toastrackenigma
fonte
3

Por que você não usa apenas algum elemento de referência no início do seu arquivo html, como

<div id="top"></div>

e então, quando a página carregar, simplesmente faça

$(document).ready(function(){

    top.location.href = '#top';

});

Se o navegador rolar após o acionamento desta função, você simplesmente

$(window).load(function(){

    top.location.href = '#top';

});
arik
fonte
3
Isso funcionou para mim, mas acrescenta a #top na url, você pode me dizer como posso evitar isso, mas ao mesmo tempo, não comprometer com a funcionalidade
Abbas
3

Percorra o navegador para o topo:

        if($('body').scrollTop()>0){
            $('body').scrollTop(0);         //Chrome,Safari
        }else{
            if($('html').scrollTop()>0){    //IE, FF
                $('html').scrollTop(0);
            }
        } 

Role entre navegadores até um elemento com id = div_id:

        if($('body').scrollTop()>$('#div_id').offset().top){
            $('body').scrollTop($('#div_id').offset().top);         //Chrome,Safari
        }else{
            if($('html').scrollTop()>$('#div_id').offset().top){    //IE, FF
                $('html').scrollTop($('#div_id').offset().top);
            }
        } 
Binod Kalathil
fonte
2

Para responder à sua pergunta editada, você pode registrar o onscrollmanipulador da seguinte maneira:

document.documentElement.onscroll = document.body.onscroll = function() {
    this.scrollTop = 0;
    this.onscroll = null;
}

Isso fará com que a primeira tentativa de rolagem (provavelmente a automática feita pelo navegador) seja efetivamente cancelada.

Niet, o Escuro Absol
fonte
Solução agradável - vou tentar
Yarin
2

Se você estiver no modo quircks (obrigado @Niet the Dark Absol):

document.body.scrollTop = document.documentElement.scrollTop = 0;

Se você estiver no modo estrito:

document.documentElement.scrollTop = 0;

Não há necessidade de jQuery aqui.


fonte
2

Isso está funcionando:

jQuery(document).ready(function() {
     jQuery("html").animate({ scrollTop: 0 }, "fast");
});
srdjanprpa
fonte
2

No meu caso, o corpo não funcionou:

$('body').scrollTop(0);

Mas o HTML funcionou:

$('html').scrollTop(0);
Sachin Prasad
fonte
1
Adicionar tanto 'html','body'como os navegadores modernos FF, Chrome irá rolar com base no corpo, mas IE8 e abaixo somente irá rolar com'html','body'
Rajesh
2

A combinação desses dois me ajudou. Nenhuma das outras respostas me ajudou, pois eu tinha um sidenav que não estava rolando.

 setTimeout(function () {
        window.scroll({
                        top: 0,
                        left: 0,
                        behavior: 'smooth'
                    });

    document.body.scrollTop = document.documentElement.scrollTop = 0;

}, 15);
shailesh gavathe
fonte
1
var totop = $('#totop');
totop.click(function(){
 $('html, body').stop(true,true).animate({scrollTop:0}, 1000);
 return false;
});

$(window).scroll(function(){
 if ($(this).scrollTop() > 100){ 
  totop.fadeIn();
 }else{
  totop.fadeOut();
 }
});

<img id="totop" src="img/arrow_up.png" title="Click to go Up" style="display:none;position:fixed;bottom:10px;right:10px;cursor:pointer;cursor:hand;"/>
user3178603
fonte
1

sem animação, apenas scroll(0, 0)(baunilha JS)

maxbellec
fonte
1

Se alguém estiver usando design angular e de material com o sidenav. Isso o enviará para o topo da página:

let ele = document.getElementsByClassName('md-sidenav-content');
    let eleArray = <Element[]>Array.prototype.slice.call(ele);
    eleArray.map( val => {
        val.scrollTop = document.documentElement.scrollTop = 0;
    });
Helzgate
fonte
0

Veja que o hash deve fazer o trabalho. Se você tem um cabeçalho, pode usar

window.location.href = "#headerid";

caso contrário, o # sozinho funcionará

window.location.href = "#";

E, à medida que for escrito no URL, ele permanecerá se você atualizar.

De fato, você não precisa de JavaScript para isso. Se quiser fazê-lo em um evento onclick, basta colocar um link ao seu redor e dar # como href.

xavierm02
fonte
Btw, window.location não faz parte da árvore, então agora é usado para aguardar a carga.
Xavierm02 27/05
0

Primeiro, adicione uma marca de âncora em branco ao local para onde deseja ir

<a href="#topAnchor"></a> 

Agora adicione uma função na seção de cabeçalho

 function GoToTop() {
            var urllocation = location.href;
            if (urllocation.indexOf("#topAnchor") > -1) {
                window.location.hash = "topAnchor";
            } else {
                return false;
            }
        }

finalmente adicione um evento onload à tag body

<body onload="GoToTop()">
Satii
fonte
0

Uma versão genérica que funciona para qualquer valor X e Y e é igual à API window.scrollTo, apenas com a adição de scrollDuration.

* Uma versão genérica correspondente à API window.scrollTo do navegador **

function smoothScrollTo(x, y, scrollDuration) {
    x = Math.abs(x || 0);
    y = Math.abs(y || 0);
    scrollDuration = scrollDuration || 1500;

    var currentScrollY = window.scrollY,
        currentScrollX = window.scrollX,
        dirY = y > currentScrollY ? 1 : -1,
        dirX = x > currentScrollX ? 1 : -1,
        tick = 16.6667, // 1000 / 60
        scrollStep = Math.PI / ( scrollDuration / tick ),
        cosParameterY = currentScrollY / 2,
        cosParameterX = currentScrollX / 2,
        scrollCount = 0,
        scrollMargin;

    function step() {        
        scrollCount = scrollCount + 1;  

        if ( window.scrollX !== x ) {
            scrollMargin = cosParameterX + dirX * cosParameterX * Math.cos( scrollCount * scrollStep );
            window.scrollTo( 0, ( currentScrollX - scrollMargin ) );
        } 

        if ( window.scrollY !== y ) {
            scrollMargin = cosParameterY + dirY * cosParameterY * Math.cos( scrollCount * scrollStep );
            window.scrollTo( 0, ( currentScrollY - scrollMargin ) );
        } 

        if (window.scrollX !== x || window.scrollY !== y) {
            requestAnimationFrame(step);
        }
    }

    step();
}
jamesmfriedman
fonte
0

Lembro-me de ver isso postado em outro lugar (não consegui encontrar onde), mas isso funciona muito bem:

setTimeout(() => {
    window.scrollTo(0, 0);
}, 0);

É estranho, mas o modo como funciona é baseado na maneira como a fila de pilhas do JavaScript funciona. A explicação completa pode ser encontrada aqui na seção Atraso Zero.

A ideia básica é que o tempo para setTimeoutrealmente não especifique a quantidade de tempo que irá esperar, mas a quantidade mínima de tempo que irá esperar. Portanto, quando você diz para esperar 0ms, o navegador executa todos os outros processos na fila (como rolar a janela para onde você estava por último) e, em seguida, executa o retorno de chamada.

Greyson R.
fonte
-1
 <script>
  sessionStorage.scrollDirection = 1;//create a session variable 
  var pageScroll = function() {
  window.scrollBy ({
   top: sessionStorage.scrollDirection,
   left: 0,
   behavior: 'smooth'
   });
   if($(window).scrollTop() + $(window).height() > $(document).height() - 1)
  {    
    sessionStorage.scrollDirection= Number(sessionStorage.scrollDirection )-300;
    setTimeout(pageScroll,50);//
   }
   else{
   sessionStorage.scrollDirection=Number(sessionStorage.scrollDirection )+1
   setTimeout(pageScroll,300); 
  }
};
pageScroll();
</script>
Kenrick Humber
fonte
1
Bem-vindo ao stackoverflow. Além do código que você forneceu, tente dar uma explicação sobre por que e como isso corrige o problema.
jtate