¿Cómo desplazar la página HTML al anclaje dado?

264

Me gustaría hacer que el navegador desplace la página a un anclaje determinado, simplemente usando JavaScript.

He especificado un atributo nameo iden mi código HTML:

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

o

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

Me gustaría obtener el mismo efecto que obtendrías navegando http://server.com/path#anchorName. La página debe desplazarse para que el ancla esté cerca de la parte superior de la parte visible de la página.

Juha Syrjälä
fuente

Respuestas:

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

¡No se requiere jQuery en absoluto!

Dean Harding
fuente
92
Sin embargo, eso en realidad no se desplaza, solo salta. En ese punto, también podrías vincular al ancla<a href="#anchorName">link</a>
Ryan
52
Tenga en cuenta que esto solo funcionará una vez. Una vez que se establece el hash, la página no se desplazará al mismo hash a menos que lo cambie a uno ficticio y luego lo configure nuevamente.
Cristian Vrabie
13
No debe usar scrollTo, porque ya lo usa el objeto de ventana global. Además, el parámetro no debe llamarse hash, porque location.hash también está definido. Puede usar este código:function scrollToHash(hashName) { location.hash = "#" + hashName; }
Markus Zeller
3
@MarkusZeller, ¿por qué el parámetro no debería llamarse hash? No choca con la ubicación, ¿verdad?
Gherman
3
esto se desplaza si establece "scroll-behaviour: smooth;" en el elemento html
stackers
225

Manera más simple:

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
fuente
22
Al principio pensé que Mandx estaba trolleando, luego lo intenté y funcionó. Más allá de mí, cómo nunca me encontré con este método antes. Mozilla Docs para este método . Además, parece que esto será muy bien compatible con los navegadores.
Jonathan Dumaine
2
He tenido muchos problemas con las soluciones jquery que no se desplazan. Esto me salvó mucha frustración.
NuclearPeon
1
¡ADVERTENCIA! Este método puede tener problemas si un div encima contiene elementos flotantes y no puede determinar su tamaño fácilmente.
vogomatix
55
Esta es una solución limpia, sin embargo, a partir de ahora no permite ningún ajuste, hace un desplazamiento duro. Hay un parámetro experimental scrollIntoViewOptionsque tiene una behavior: "smooth"opción, pero actualmente solo es compatible con Firefox.
rocha
¿Cómo animar esto?
SkuraZZ
124

Puede usar jQuerys .animate () , .offset () y scrollTop. Me gusta

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

enlace de ejemplo: http://jsbin.com/unasi3/edit

Si no desea animar, use .scrollTop () como

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

o javascripts nativos location.hashcomo

location.hash = '#' + anchorid;
jAndy
fuente
1
En cuanto a la creación de un selector para encontrar el <h1 id="anchorName">o an <a name="anchorName">, use $('#'+hash+',a[name='+hash+']')u ligeramente optimizado, $(document.getElementById(hash) || 'a[name='+hash+']')que buscará el elemento por ID primero, y recurrirá a buscar los a's solo si no se encuentra uno.
gnarf
@gnarf: no es necesario optimizar los selectores '#' en jQuery, ya están optimizados para usted. Es bastante fácil ver si has leído el código fuente de jQuery.
CodeJoust
3
@CodeJoust: estoy en el equipo de jQuery, lo he leído muchas veces y sí $("#selector")está optimizado, pero $("#selector,a[name='selector']")no pasaré por las mismas optimizaciones tan rápido. Supongo que mi comentario de 2.5 años es un poco extraño. La "optimización" está evitando la a[name='selector']búsqueda si encuentra la identificación, no optimizando la búsqueda de la identificación.
Gnarf
1
Tuve suerte con este enfoque: <a data-hash="about"> Acerca de </a> <script> $ ("[data-hash]"). Click (function () {var data = $ (this) .attr ("data-hash"); $ (document.body) .animate ({'scrollTop': $ ("#" + data) .offset (). top}, 500);}); </script>
Jazzy
33

Gran solución de jAndy, pero el desplazamiento suave parece tener problemas para trabajar en Firefox.

Escribirlo de esta manera también funciona en Firefox.

(function($) {
    $(document).ready(function() {
         $('html, body').animate({
           'scrollTop':   $('#anchorName2').offset().top
         }, 2000);
    });
})(jQuery);
5hahiL
fuente
En la última versión de Chrome, este es el único método que he encontrado que funciona constantemente. ¡Gracias por el consejo!
gaborous
32

2018-2020 Pure js:

Hay una forma muy conveniente de desplazarse al 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.
})

Pero por lo que yo entiendo, él no tiene un apoyo tan bueno como las opciones a continuación.

ingrese la descripción de la imagen aquí

Aprende más sobre el método.


Si es necesario que el elemento esté en la parte superior:

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
})

Ejemplo de demostración en Codepen


Si desea que el elemento esté en el 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
});

Ejemplo de demostración en Codepen


Apoyo:

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

Escriben que scrolles el mismo método que scrollTo, pero el soporte se muestra mejor en scrollTo.

Más sobre el método

Илья Зеленько
fuente
¡Esta solución funciona muy, muy bien! ¡Gracias por compartir!
gaborous
29

Una solución javascript pura sin JQuery. Probado en Chrome e Ie, no probado en 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
fuente
1
Disculpas por comentar sobre un tema antiguo, pero esto funciona mejor para mí ya que mi proyecto no está utilizando JQuery. El único problema que noté es que pierde 5 píxeles más o menos si te desplazas hacia la parte superior.
AntBirch
Muy refrescante ver una versión js pura. Enseño a los estudiantes a mirar siempre debajo del capó y comprender lo que JQuery hace por ellos, así que este es un buen ejemplo.
Dave Everitt
2
Esta debería ser la respuesta aceptada: es un ejemplo js puro Y logra el efecto de animación de desplazamiento deseado. Ajusté el valor del tiempo de espera a 20 y funciona a la perfección.
Mark Barrasso
Gracias Me encantan las soluciones javascript puras
R01010010
2
Funciona en iOS lo acabo de probar.
Debbie Kurth
23

En 2018, no necesita jQuery para algo simple como esto. El scrollIntoView()método integrado admite una behaviorpropiedad " " para desplazarse sin problemas a cualquier elemento de la página. Incluso puede actualizar la URL del navegador con un hash para que se pueda marcar como favorito.

De este tutorial sobre desplazamiento de marcadores HTML , aquí hay una forma nativa de agregar desplazamiento suave a todos los enlaces de anclaje en su página automáticamente:

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()
    })
}
hojaldres de coco
fuente
2
Excelente respuesta que elimina la dependencia de jQuery
zai chang
¡Guauu! Funciona genial!
Alexandru Trandafir Catalin
14

Desplácese suavemente a la posición correcta (2019)

Obtenga la y coordenada correcta y 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'});

Con desplazamiento

scrollIntoViewTambién es una buena opción, pero puede no funcionar perfectamente en algunos casos. Por ejemplo, cuando necesita un desplazamiento adicional . Con scrollTosolo necesita agregar ese desplazamiento de esta manera:

const yOffset = -10; 

window.scrollTo({top: y + yOffset, behavior: 'smooth'});
Arseniy-II
fuente
Creo que debería agregar lo siguiente al archivo de estilo CSS: css html { scroll-behavior: smooth; }
parismiguel
5
$(document).ready ->
  $("a[href^='#']").click ->
    $(document.body).animate
      scrollTop: $($(this).attr("href")).offset().top, 1000
cactus
fuente
5

La solución de CSS-Tricks ya no funciona en jQuery 2.2.0. Lanzará un error de selector:

Error de tiempo de ejecución de JavaScript: error de sintaxis, expresión no reconocida: a [href * = #]: not ([href = #])

Lo arreglé cambiando el selector. El fragmento completo es 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
fuente
4

La mayoría de las respuestas son innecesariamente complicadas.

Si solo quiere saltar al elemento de destino, no necesita JavaScript:

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

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

Si desea desplazarse al objetivo animadamente , consulte la respuesta de @ Shahil.

Brian
fuente
Sin embargo, a veces, debes hacerlo dinámicamente; es decir, a través de ninguna acción directa del usuario. Creo que eso es lo que quiere el OP.
jpaugh
1
Sí, claramente el OP ya estaba al tanto de la funcionalidad de enlace de anclaje.
isherwood
4

Esto 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/

Simplemente agregue la clase 'scroll' a cualquier enlace que desee animar

Chuck Le Butt
fuente
Buena solución, fácil de usar. ¡Gracias!
Smitty-Werben-Jager-Manjenson
3

Este es un script de trabajo que desplazará la página al delimitador. Para la configuración, simplemente proporcione al enlace de anclaje una identificación que coincida con el atributo de nombre del anclaje al que desea desplazarse.

<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
fuente
2

Sé que esta pregunta es muy antigua, pero encontré una solución jQuery fácil y simple en css-tricks . Ese es el que estoy usando ahora.

$(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
fuente
1
El selector está lanzando una excepción en jquery 2.2.0. 0x800a139e - Error de tiempo de ejecución de JavaScript: error de sintaxis, expresión no reconocida: a [href * = #]: not ([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
fuente
2

una solución vue2 ... agregue una propiedad de datos simple para simplemente forzar la actualización

  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
fuente
0

la forma más fácil de hacer que el navegador desplace la página a un anclaje dado es escribir su style.css * {scroll-behaviour: smooth;} y en su navegación 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
fuente