¿Qué pasa con mi código? scrollTo() va a la posición incorrecta cuando hago clic y ancla con el valor href usando el hash # (ID del elemento div).
Este es mi código, solo quiero desplazarme hasta el elemento de comentario, pero aún superpuesto en el encabezado fijo (encabezado fijo de bootstrap 5).
if (document.querySelectorAll('a').length) { document.querySelectorAll('a').forEach( anchor => { anchor.addEventListener('click', event => { let URL = event.target.href.split('#'); if (typeof URL[1] != undefined) { let element = document.getElementById(URL[1]); let offset = element.offsetTop; let navigation = document.getElementById('main-navigation').clientHeight let scroll = offset - navigation; window.scrollTo(0, scroll); } }); }); }¿Alguien puede ayudarme?
Puede lograrlo usando la función scrollIntoView() . vea el siguiente ejemplo. tienes que apuntar al elemento para desplazarte:
let i = 0; function myFunction() { if(i === 0){ const elmnt = document.getElementById("content"); elmnt.scrollIntoView(); i += 1 } else { const elmnt = document.getElementById("content2"); elmnt.scrollIntoView(); } } #myDIV { height: 250px; width: 250px; overflow: auto; background: green; } #content { margin:500px; height: 800px; width: 2000px; background-color: coral; } #content2 { margin:500px; height: 800px; width: 2000px; background-color: red; } <p>Click the button to scroll to section.</p> <button onclick="myFunction()">Scroll</button> <div id="myDIV"> <div id="content"> Some text inside an element. </div> <div id="content2"> Some text inside an element. </div> </div>Llame event.preventDefault() en el controlador de clics , de lo contrario, después de su llamada a scrollTo , el hash de la página cambiará, con un desplazamiento automático al elemento anclado anulando el suyo.
document.querySelectorAll('a').forEach( anchor => { anchor.addEventListener('click', event => { let URL = event.target.href.split('#'); if (typeof URL[1] != undefined) { let element = document.getElementById(URL[1]); let offset = element.offsetTop; let navigation = document.querySelector('.over').clientHeight let scroll = offset - navigation; window.scrollTo(0, scroll); event.preventDefault(); // avoid internal scroll to anchor } }); }); .over { height: 50px; background: salmon; position: sticky; top: 0; } #foo { margin-top: 250vh; height: 250vh; } <a href="#foo">#foo</a> <div class="over"></div> <div id="foo">Target element</div>Lo más importante es que debe detener el comportamiento predeterminado. Cuando se hace clic en un enlace interno, la acción predeterminada es saltar a ese enlace. Tienes que anular eso.
A continuación, podemos hacer un par de pequeños ajustes. Primero, solo seleccione enlaces internos con a selector de atributos que seleccione etiquetas donde el href comience con "#". Luego, en lugar de dividir la URL del href, tome el valor sin procesar directamente del atributo.
//Get internal links document.querySelectorAll("a[href^='#']").forEach(function(el) { el.addEventListener("click", function(e) { //Stops the inbuild scroll e.preventDefault(); //Get the id straight from the attribute let selector = this.getAttribute("href"); //Get the target element let element = document.querySelector(selector); //you know the rest let offset = element.offsetTop; let navigation = document.getElementById('main-navigation').clientHeight let scroll = offset - navigation; window.scrollTo(0, scroll); }); }); /*CSS Purely for demo purposes.*/ .fixed-top { background-color: #EEE; padding: 15px; } article:first-of-type{ margin-top:90px; } article { min-height: 50vh; border-bottom: 1px solid black; } nav { background-color: #ECECEC; } <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> <div class="fixed-top" id="main-navigation">Some Top Stuff <nav> <a href="#art1">Article 1</a> <a href="#art2">Article 2</a> <a href="#art3">Article 3</a> </nav> </div> <article id="art1"> <h1>Article 1</h1> </article> <article id="art2"> <h1>Article 2</h1> </article> <article id="art3"> <h1>Article 3</h1> </article>