¿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.

Respuestas:


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

¡No se requiere jQuery en absoluto!


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();

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;

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

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


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


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

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

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

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

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.


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


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>

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

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


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

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>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.