Piotr Berebecki Piotr Berebecki - 1 month ago 9
Javascript Question

Scroll animation in vanilla JavaScript works only for navigation links

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


  1. Top navigation links, and

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

Answer

Try removing the # anchor from the href in your tag:

<a href="javascript:void(0);" class="back-to-top">Back to Top</a>

Updated pen: http://codepen.io/anon/pen/YGbBXz

Here's a great reference question/answer that should address any further questions about href="#" and the href property inclusion: What is href="#" and why is it used?

Summarizing the above post (in regards to question in the comments):

href="#" targets the top of the page.

href is required ONLY in the event the anchor tag is meant to be a hyperlink.