Here is a codepen which demonstrates my problem: http://codepen.io/PiotrBerebecki/pen/yaWQwZ
The objective is to have a scrolling animation when the user clicks on the
- Top navigation links, and
Back to Top
button in the bottom right corner.
I've managed to implement a vanilla JavaScript solution that meets requirement 1 but I'm struggling with requirement 2.
The solution relies on a recursive scrollTo
function.
As you can see when you scroll down and click on the My work
link, the animation runs correctly. However when you scroll down and click on the Back to Top
button there is no animation and the page just jumps to top. I can't figure out why and how to fix it.
Here is the JS code:
(function() {
// ======== SCROLL FUNCTION ======== //
const scrollTo = (element, to, duration) => {
if (duration <= 0) {return;}
var difference = to - element.scrollTop;
var perTick = difference / duration * 10;
setTimeout(() => {
element.scrollTop = element.scrollTop + perTick;
if (element.scrollTop === to) {return;}
scrollTo(element, to, duration - 10);
}, 10);
}
// ======== TOP NAVIGATION ======== //
// Save DOM elements that can be scrolled to
let targetElements = {};
(function() {
const myWork = document.getElementById('my-work');
const contact = document.getElementById('contact');
targetElements = {
'my-work': myWork,
contact: contact
};
})();
// Select links with scroll action
const scrollElements = document.getElementsByClassName('scroll');
// Add event listeners to navigation links with scroll action
Array.prototype.forEach.call(scrollElements, scrollElement => {
scrollElement.addEventListener('click', event => {
event.preventDefault();
const targetElement = targetElements[(scrollElement.getAttribute('href').slice(1))];
scrollTo(document.body, targetElement.offsetTop, 800);
});
});
// ======== BACK TO TOP BUTTON ======== //
const backToTopElement = document.getElementsByClassName('back-to-top')[0];
const backToTopTargetElement = document.getElementById('my-work');
backToTopElement.addEventListener('click', () => {
scrollTo(document.body, backToTopTargetElement.offsetTop, 800);
});
})();
Here is the HTML (the Back to Top
button is at the bottom):
<!-- ======== NAVIGATION ======== -->
<nav role='navigation'>
<div id="logo-container">
<a class="scroll" href="#my-work">SUPER CAT</a>
</div>
<ul id="menu">
<li><a class="scroll menu-link" href="#my-work">MY WORK</a></li>
<li><a class="scroll menu-link" href="#contact">CONTACT</a></li>
</ul>
</nav>
<!-- ======== MY WORK ======== -->
<article id="my-work">
<header>
<h1>MY WORK</h1>
</header>
...
</article>
<!-- ======== CONTACT ======== -->
<footer id="contact">
<h2>CONTACT</h2>
...
</footer>
<a href="#" class="back-to-top">Back to Top</a>