UPD: criei um pacote npm que funciona melhor do que a solução a seguir e mais fácil de usar.
Minha função smoothScroll
Peguei a solução maravilhosa de Steve Banton e escrevi uma função que a torna mais conveniente de usar. Seria mais fácil de usar window.scroll()
ou até mesmo window.scrollBy()
, como já tentei antes, mas esses dois têm alguns problemas:
- Tudo fica viciado depois de usá-los com um comportamento suave.
- Você não pode evitá-los de qualquer maneira e tem que esperar até o fim do livro. Espero que minha função seja útil para você. Além disso, há um polyfill leve que o faz funcionar no Safari e até no IE.
Aqui está o código
Basta copiá-lo e bagunçar como quiser.
import smoothscroll from 'smoothscroll-polyfill';
smoothscroll.polyfill();
const prepareSmoothScroll = linkEl => {
const EXTRA_OFFSET = 0;
const destinationEl = document.getElementById(linkEl.dataset.smoothScrollTo);
const blockOption = linkEl.dataset.smoothScrollBlock || 'start';
if ((blockOption === 'start' || blockOption === 'end') && EXTRA_OFFSET) {
const anchorEl = document.createElement('div');
destinationEl.setAttribute('style', 'position: relative;');
anchorEl.setAttribute('style', `position: absolute; top: -${EXTRA_OFFSET}px; left: 0;`);
destinationEl.appendChild(anchorEl);
linkEl.addEventListener('click', () => {
anchorEl.scrollIntoView({
block: blockOption,
behavior: 'smooth',
});
});
}
if (blockOption === 'center' || !EXTRA_OFFSET) {
linkEl.addEventListener('click', () => {
destinationEl.scrollIntoView({
block: blockOption,
behavior: 'smooth',
});
});
}
};
export const activateSmoothScroll = () => {
const linkEls = [...document.querySelectorAll('[data-smooth-scroll-to]')];
linkEls.forEach(linkEl => prepareSmoothScroll(linkEl));
};
Para fazer um elemento de link, basta adicionar o seguinte atributo de dados:
data-smooth-scroll-to="element-id"
Além disso, você pode definir outro atributo como um complemento
data-smooth-scroll-block="center"
Representa a block
opção da scrollIntoView()
função. Por padrão, é start
. Leia mais sobre MDN .
Finalmente
Ajuste a função smoothScroll às suas necessidades.
Por exemplo, se você tem algum cabeçalho fixo (ou eu o chamo com a palavra masthead
), pode fazer algo assim:
const mastheadEl = document.querySelector(someMastheadSelector);
// and add it's height to the EXTRA_OFFSET variable
const EXTRA_OFFSET = mastheadEl.offsetHeight - 3;
Se você não tiver esse caso, basta excluí-lo, por que não :-D.
scrollIntoView
é preocupante.