Como rolar a página HTML para a âncora fornecida?

264

Gostaria de fazer o navegador rolar a página até uma determinada âncora, apenas usando JavaScript.

Eu especifiquei um nameou idatributo no meu código HTML:

 <a name="anchorName">..</a>

ou

 <h1 id="anchorName2">..</h1>

Gostaria de obter o mesmo efeito que você navegaria para http://server.com/path#anchorName. A página deve ser rolada para que a âncora fique perto do topo da parte visível da página.

Juha Syrjälä
fonte

Respostas:

349
function scrollTo(hash) {
    location.hash = "#" + hash;
}

Não é necessário jQuery!

Dean Harding
fonte
92
Na verdade, isso não rola, apenas salta. Nesse ponto você pode muito bem fazer o link com a âncora<a href="#anchorName">link</a>
Ryan
52
Observe que isso funcionará apenas uma vez. Depois que o hash estiver definido, a página não irá rolar para o mesmo hash, a menos que você o altere para simulado e o defina novamente.
precisa
13
Você não deve usar scrollTo, porque ele já é usado pelo objeto de janela global. Além disso, o parâmetro não deve ser chamado de hash, porque location.hash também está definido. Você pode usar este código:function scrollToHash(hashName) { location.hash = "#" + hashName; }
Markus Zeller
3
@ MarkusZeller, por que o parâmetro não deve ser chamado de hash? Ele não colide com a localização, não é?
Gherman
3
isso rolará se você definir "comportamento de rolagem: suave;" no elemento html
stackers
225

Muito mais simples:

var element_to_scroll_to = document.getElementById('anchorName2');
// Or:
var element_to_scroll_to = document.querySelectorAll('.my-element-class')[0];
// Or:
var element_to_scroll_to = $('.my-element-class')[0];
// Basically `element_to_scroll_to` just have to be a reference
// to any DOM element present on the page
// Then:
element_to_scroll_to.scrollIntoView();
Armando Pérez Marqués
fonte
22
A princípio, pensei que Mandx estava trollando, depois tentei e funcionou. Além de mim, como nunca me deparei com esse método antes. Mozilla Docs para esse método . Além disso, parece que isso será muito bem suportado nos navegadores.
Jonathan Dumaine
2
Eu tive muitos problemas com as soluções jquery que não rolavam. Isso me salvou de muita frustração.
NuclearPeon
1
AVISO! Este método pode ter problemas se uma div acima contiver elementos flutuantes e não puder determinar seu tamanho facilmente.
vogomatix 3/17/17
5
Esta é uma solução limpa, no entanto, a partir de agora, não permite ajustes, faz uma rolagem rígida. Há um parâmetro experimental scrollIntoViewOptionsque tem uma behavior: "smooth"opção, mas atualmente é compatível apenas com o Firefox.
rocha
Como animar isso?
precisa saber é o seguinte
124

Você pode usar jQuerys .animate () , .offset () e scrollTop. Gostar

$(document.body).animate({
    'scrollTop':   $('#anchorName2').offset().top
}, 2000);

link de exemplo: http://jsbin.com/unasi3/edit

Se você não deseja animar, use .scrollTop () como

$(document.body).scrollTop($('#anchorName2').offset().top);

ou javascripts nativos location.hashcomo

location.hash = '#' + anchorid;
jAndy
fonte
1
No que diz respeito à criação de um seletor para encontrar o <h1 id="anchorName">ou um <a name="anchorName">, use $('#'+hash+',a[name='+hash+']')ou ligeiramente otimizado, $(document.getElementById(hash) || 'a[name='+hash+']')que procurará o elemento pelo ID primeiro e recorrerá à busca do a apenas se um não for encontrado.
Gnarf
@gnarf - Não há necessidade de otimizar os seletores '#' no jQuery - eles já estão otimizados para você. É bastante fácil ver se você leu o código fonte do jQuery.
precisa saber é o seguinte
3
@CodeJoust - Estou na equipe do jQuery, já o li muitas vezes, e sim $("#selector")é otimizado, mas $("#selector,a[name='selector']")não passará pelas mesmas otimizações o mais rápido possível. Suponho que meu comentário de 2,5 anos seja um pouco estranho. A "otimização" está evitando a a[name='selector']pesquisa se encontrar o ID, não otimizando a pesquisa pelo ID.
Gnarf
1
Tive alguma sorte com esta abordagem: <a data-hash="about"> Sobre </a> <script> $ ("[data-hash]"). Click (function () {var data = $ (this) .attr ("data-hash"); $ (document.body) .animate ({'scrollTop': $ ("#" + dados) .offset (). top}, 500);}); </script>
Jazzy
33

Ótima solução da jAndy, mas o bom scroll parece estar tendo problemas ao trabalhar no firefox.

Escrever dessa maneira também funciona no Firefox.

(function($) {
    $(document).ready(function() {
         $('html, body').animate({
           'scrollTop':   $('#anchorName2').offset().top
         }, 2000);
    });
})(jQuery);
5hahiL
fonte
Na versão mais recente do Chrome, esse é o único método que encontrei que funciona de maneira consistente. Obrigado pela dica!
gaborous 06/06
32

2018-2020 Pure js:

Existe uma maneira muito conveniente de rolar para o elemento:

el.scrollIntoView({
  behavior: 'smooth', // smooth scroll
  block: 'start' // the upper border of the element will be aligned at the top of the visible part of the window of the scrollable area.
})

Mas, tanto quanto eu entendo, ele não tem um apoio tão bom quanto as opções abaixo.

insira a descrição da imagem aqui

Saiba mais sobre o método


Se for necessário que o elemento esteja no topo:

const element = document.querySelector('#element')
const topPos = element.getBoundingClientRect().top + window.pageYOffset

window.scrollTo({
  top: topPos, // scroll so that the element is at the top of the view
  behavior: 'smooth' // smooth scroll
})

Exemplo de demonstração no Codepen


Se você deseja que o elemento esteja no centro:

const element = document.querySelector('#element')
const rect = element.getBoundingClientRect() // get rects(width, height, top, etc)
const viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);

window.scroll({
  top: rect.top + rect.height / 2 - viewHeight / 2,
  behavior: 'smooth' // smooth scroll
});

Exemplo de demonstração no Codepen


Apoio, suporte:

введите сюда описание изображения

Eles escrevem que scrollé o mesmo método quescrollTo , mas o suporte mostra melhor scrollTo.

Mais sobre o método

Илья Зеленько
fonte
Esta solução funciona muito, muito bem! Obrigado por compartilhar!
gaborous 06/06
29

Uma solução javascript pura sem JQuery. Testado no Chrome e Ie, não testado no IOS

function ScrollTo(name) {
  ScrollToResolver(document.getElementById(name));
}

function ScrollToResolver(elem) {
  var jump = parseInt(elem.getBoundingClientRect().top * .2);
  document.body.scrollTop += jump;
  document.documentElement.scrollTop += jump;
  if (!elem.lastjump || elem.lastjump > Math.abs(jump)) {
    elem.lastjump = Math.abs(jump);
    setTimeout(function() { ScrollToResolver(elem);}, "100");
  } else {
    elem.lastjump = null;
  }
}

demo: https://jsfiddle.net/jd7q25hg/12/

Michael Whinfrey
fonte
1
Desculpas por comentar sobre um tópico antigo, mas isso funciona melhor para mim, pois meu projeto não está usando o JQuery. O único problema que notei é que ele perde 5 pixels ou mais, se você rolar até o topo.
AntBirch
Muito refrescante para ver uma versão js pura. Eu ensino os alunos a sempre procurarem entender o que o JQuery faz por eles, portanto esse é um bom exemplo.
Dave Everitt
2
Esta deve ser a resposta aceita: é um exemplo js puro E atinge o efeito de animação de rolagem desejado. Ajustei o valor do tempo limite para 20 e ele funciona perfeitamente.
Mark Barrasso #
Obrigado Eu amo soluções puro javascript
R01010010
2
Funciona no IOS apenas testou.
Debbie Kurth 18/02
23

Em 2018, você não precisa do jQuery para algo simples como este. O scrollIntoView()método interno suporta um "behavior propriedade " para rolar suavemente para qualquer elemento da página. Você pode até atualizar o URL do navegador com um hash para torná-lo favorito.

A partir deste tutorial sobre rolagem HTML Bookmarks , aqui é uma maneira nativa para adicionar rolagem suave para todos os links de âncora em sua página automaticamente:

let anchorlinks = document.querySelectorAll('a[href^="#"]')
 
for (let item of anchorlinks) { // relitere 
    item.addEventListener('click', (e)=> {
        let hashval = item.getAttribute('href')
        let target = document.querySelector(hashval)
        target.scrollIntoView({
            behavior: 'smooth',
            block: 'start'
        })
        history.pushState(null, null, hashval)
        e.preventDefault()
    })
}
sopros de coco
fonte
2
Excelente resposta que remove a dependência do jQuery
zai chang
Uau! Works awesome!
Alexandru Trandafir Catalin
14

Role suavemente para a posição correta (2019)

Obtenha a y coordenada correta e usewindow.scrollTo({top: y, behavior: 'smooth'})

const id = 'anchorName2';
const yourElement = document.getElementById(id);
const y = yourElement.getBoundingClientRect().top + window.pageYOffset;

window.scrollTo({top: y, behavior: 'smooth'});

Com deslocamento

scrollIntoViewtambém é uma boa opção, mas pode não funcionar perfeitamente em alguns casos. Por exemplo, quando você precisar de deslocamento adicional . Com scrollTovocê, basta adicionar esse deslocamento assim:

const yOffset = -10; 

window.scrollTo({top: y + yOffset, behavior: 'smooth'});
Arseniy-II
fonte
Eu acho que você deve adicionar o seguinte ao arquivo de estilo CSS: css html { scroll-behavior: smooth; }
parismiguel 9/09/19
5
$(document).ready ->
  $("a[href^='#']").click ->
    $(document.body).animate
      scrollTop: $($(this).attr("href")).offset().top, 1000
cactis
fonte
5

A solução do CSS-Tricks não funciona mais no jQuery 2.2.0. Irá gerar um erro de seletor:

Erro de tempo de execução do JavaScript: erro de sintaxe, expressão não reconhecida: a [href * = #]: not ([href = #])

Corrigi-o alterando o seletor. O trecho completo é este:

$(function() {
  $("a[href*='#']:not([href='#'])").click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
    var target = $(this.hash);
    target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
    if (target.length) {
      $('html,body').animate({
        scrollTop: target.offset().top
      }, 1000);
      return false;
    }
  }
 });
});
Bill Shihara
fonte
4

A maioria das respostas é desnecessariamente complicada.

Se você quiser apenas pular para o elemento de destino, não precisa de JavaScript:

# the link:
<a href="#target">Click here to jump.</a>

# target element:
<div id="target">Any kind of element.</div>

Se você quiser rolar animadamente para o alvo , consulte a resposta de @ Shahil.

Brian
fonte
Às vezes, você precisa fazer isso dinamicamente; ou seja, através de nenhuma ação direta do usuário. Eu acredito que é isso que o OP quer.
jpaugh
1
Sim, claramente o OP já estava ciente da funcionalidade do link de âncora.
Isherwood
4

Isso funciona:

$('.scroll').on("click", function(e) {

  e.preventDefault();

  var dest = $(this).attr("href");

  $("html, body").animate({

    'scrollTop':   $(dest).offset().top

  }, 2000);

});

https://jsfiddle.net/68pnkfgd/

Basta adicionar a classe 'scroll' a todos os links que você deseja animar

Chuck Le Butt
fonte
Solução agradável e simples de usar. Obrigado!
Smitty-Werben-Jager-Manjenson
3

Este é um script de trabalho que irá rolar a página até a âncora. Para configurar, apenas dê ao link da âncora um ID que corresponda ao atributo name da âncora para a qual você deseja rolar.

<script>
jQuery(document).ready(function ($){ 
 $('a').click(function (){ 
  var id = $(this).attr('id');
  console.log(id);
  if ( id == 'cet' || id == 'protein' ) {
   $('html, body').animate({ scrollTop: $('[name="' + id + '"]').offset().top}, 'slow'); 
  }
 }); 
});
</script>
Rudy Lister
fonte
2

Eu sei que essa pergunta é realmente antiga, mas eu encontrei uma solução jQuery fácil e simples em CSS-Tricks . Esse é o que estou usando agora.

$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});
Horacio
fonte
1
O seletor está lançando uma exceção no jquery 2.2.0. 0x800a139e - JavaScript erro de execução: Erro de sintaxe, a expressão não reconhecida: a [href = * #]: não ([href = #])
Bill Shihara
2

jQuery("a[href^='#']").click(function(){
    jQuery('html, body').animate({
        scrollTop: jQuery( jQuery(this).attr('href') ).offset().top
    }, 1000);
    return false;
});

Adam Pery
fonte
2

uma solução vue2 ... adicione propriedade de dados simples para simplesmente forçar a atualização

  const app = new Vue({ 
  ... 

  , updated: function() {
           this.$nextTick(function() {
           var uri = window.location.href
           var anchor = ( uri.indexOf('#') === -1 ) ? '' : uri.split('#')[1]
           if ( String(anchor).length > 0 && this.updater === 'page_load' ) {
              this.updater = "" // only on page-load !
              location.href = "#"+String(anchor)
           }
         })
        }
     });
     app.updater = "page_load"

 /* smooth scrolling in css - works in html5 only */
 html, body {
     scroll-behavior: smooth;
 }
Yordan Georgiev
fonte
0

a maneira mais fácil de fazer o navegador rolar a página para uma determinada âncora é digitando seu style.css * {scroll-behavior: smooth;} e na sua navegação html use #NameOfTheSection

*{scroll-behavior: smooth;}
<a href="#scroll-to">Home<a/>

<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>
<p>other sections</p>

<section id="scroll-to">
<p>it will scroll down to this section</p>
</section>

eslam elameen
fonte