Smooth Scroll, not yet smooth due to .getElementById() not working - Help!

Smooth Scroll, not yet smooth due to .getElementById() not working - Help!
0.0 0

#1

I’m trying to create a smooth scrolling effect here, but document.getElementById() doesn’t seem to work.
(HTML line: 35; JS line:167)

Please let me know why and how it works. Feel free to give suggestions :slight_smile:


#2

I think it’s because the variable on line 162 should be technicalDetails instead of #technicalDetails. Since you are using jQuery, $('#technicalDetails')[0] should also work and is more consistent with the rest of your code in my opinion.

I hope that helps!


#3

Thanks :slight_smile: - But it still didn’t work :confused:


#4

I think the first issue is because of the href attribute in this:

<a href='#technicalDetails' class='btn' id='scrollDown'></a>

So it would just jump to #technicaldetails because it’s the default behaviour. To avoid the jumping, you can prevent the default behaviour like this:

  $('#scrollDown').click((event) => {
    event.preventDefault();
    smoothScroll();
  }

Another problem is with your smoothScroll() function, the line marginY = marginY - scrollSpeed; is actually creating an infinite recursion because marginY is only ever getting smaller. It should be marginY = marginY + scrollSpeed; instead.

Once you will have changed those, you will find that the scrolling looks “unnatural” because it scrolls at constant velocity. If you are not keen on implementing sigmoidal velocity yourself, and because you are already using window.scroll, I think you should consider changing the scroll behaviour of window.scroll() instead:

window.scroll({
  top: destination,
  behavior: 'smooth'
});

This way you don’t have to calculate marginY anymore, can avoid recursively using setTimeout (I’m personally not too keen about that), and don’t have to deal with the bug of being able to scroll down once with your current code (if I’m not mistaken, simply setting marginY to 0 when marginY >= destination doesn’t work because setTimeout() makes your smoothScroll() calls async).

It’s perhaps worth noting that if you still want to use make your on smooth-scrolling function because you want to fine tune it’s behaviour, I think you can consider using window.requestAnimationFrame() instead of setTimeout().

I hope that helps!

EDIT: Added comment about window.requestAnimationFrame().


#5

$('#technicalDetails')[0] won’t work because there is only one element with the id ‘technicalDetails’.
Instead, you should use $('#technicalDeatils').
Hope this helps.


#6

It does work because the part I was referring to is this:

const scrollID = 'technicalDetails';

// Web API
destination = document.getElementById(scrollToID).offsetTop;

// jQuery
destination = $(scrollToID)[0].offsetTop;

$('#technicalDetails')[0] === document.getElementById('technicalDetails') // true
$('#technicalDetails') === document.getElementById('technicalDetails') // false

If I’m not mistaken jQuery does select only one element when the id selection # is used, but the results is still an array of DOM elements and therefore doesn’t have the offsetTop property that we are interested in. What you suggested would work, though for something like $('#technicalDetails').css('background', '#1CE');.

I hope that helps.


#7

Oh, OK, thanks!
I didn’t realize it was being used that way.