JSFiddle - React, Tailwind, and code Playground
by Константин Дралюк
HTML
<div class="long" id="b1" style="background: yellow;">
<a href="#b1">b2</a>
<a href="#b2">b2</a>
<a href="#b3">b3</a>
<a href="#b4">b4</a>
<a href="#b5">b5</a>
</div>
<div class="long" id="b2" style="background: green;"></div>
<div class="long" id="b3" style="background: red;"></div>
<div class="long" id="b4" style="background: gray;"></div>
<div class="long" id="b5" style="background: violet;"></div>
CSS
body {
margin: 0;
}
.long {
height: 1000px;
}
JavaScript
function scrollIt(destination, duration = 200, callback) {
const easeInOutCubic = t => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
const start = window.pageYOffset;
const startTime = 'now' in window.performance ? performance.now() : new Date().getTime();
const documentHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
const windowHeight = window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName('body')[0].clientHeight;
const destinationOffset = typeof destination === 'number' ? destination : destination.offsetTop;
const destinationOffsetToScroll = Math.round(documentHeight - destinationOffset < windowHeight ? documentHeight - windowHeight : destinationOffset);
if ('requestAnimationFrame' in window === false) {
window.scroll(0, destinationOffsetToScroll);
if (callback) {
callback();
}
return;
}
function scroll() {
const now = 'now' in window.performance ? performance.now() : new Date().getTime();
const time = Math.min(1, ((now - startTime) / duration));
const timeFunction = easeInOutCubic(time);
window.scroll(0, Math.ceil((timeFunction * (destinationOffsetToScroll - start)) + start));
if (window.pageYOffset === destinationOffsetToScroll) {
if (callback) {
callback();
}
return;
}
requestAnimationFrame(scroll);
}
scroll();
}
document.querySelectorAll('a[href^="#"]').forEach($anchor => {
const href = $anchor.getAttribute('href')
const $target = document.querySelector(href)
if ($target) {
$anchor.addEventListener('click', e => {
scrollIt($target.offsetTop, 800)
e.preventDefault()
})
}
})