scrollTop animation without jquery

JavascriptJqueryHtmlCss

Javascript Problem Overview


I'm trying to make an animated "scroll to top" effect without using jQuery.

In jQuery, I usually use this code:

$('#go-to-top').click(function(){ 
      $('html,body').animate({ scrollTop: 0 }, 400);
      return false; 
});

How do I animate scrollTop without using jQuery?

Javascript Solutions


Solution 1 - Javascript

HTML:

<button onclick="scrollToTop(1000);"></button>

1# JavaScript (linear):

function scrollToTop (duration) {
	// cancel if already on top
	if (document.scrollingElement.scrollTop === 0) return;

	const totalScrollDistance = document.scrollingElement.scrollTop;
	let scrollY = totalScrollDistance, oldTimestamp = null;
  
	function step (newTimestamp) {
		if (oldTimestamp !== null) {
      		// if duration is 0 scrollY will be -Infinity
      		scrollY -= totalScrollDistance * (newTimestamp - oldTimestamp) / duration;
      		if (scrollY <= 0) return document.scrollingElement.scrollTop = 0;
      		document.scrollingElement.scrollTop = scrollY;
    	}
		oldTimestamp = newTimestamp;
		window.requestAnimationFrame(step);
	}
	window.requestAnimationFrame(step);
}

2# JavaScript (ease in and out):

function scrollToTop (duration) {
	// cancel if already on top
	if (document.scrollingElement.scrollTop === 0) return;

	const cosParameter = document.scrollingElement.scrollTop / 2;
    let scrollCount = 0, oldTimestamp = null;
  
	function step (newTimestamp) {
		if (oldTimestamp !== null) {
			// if duration is 0 scrollCount will be Infinity
			scrollCount += Math.PI * (newTimestamp - oldTimestamp) / duration;
			if (scrollCount >= Math.PI) return document.scrollingElement.scrollTop = 0;
			document.scrollingElement.scrollTop = cosParameter + cosParameter * Math.cos(scrollCount);
		}
		oldTimestamp = newTimestamp;
		window.requestAnimationFrame(step);
	}
	window.requestAnimationFrame(step);
}
/* 
  Explanation:
  - pi is the length/end point of the cosinus intervall (see below)
  - newTimestamp indicates the current time when callbacks queued by requestAnimationFrame begin to fire.
    (for more information see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame)
  - newTimestamp - oldTimestamp equals the delta time

    a * cos (bx + c) + d						| c translates along the x axis = 0
  = a * cos (bx) + d							| d translates along the y axis = 1 -> only positive y values
  = a * cos (bx) + 1							| a stretches along the y axis = cosParameter = window.scrollY / 2
  = cosParameter + cosParameter * (cos bx)	| b stretches along the x axis = scrollCount = Math.PI / (scrollDuration / (newTimestamp - oldTimestamp))
  = cosParameter + cosParameter * (cos scrollCount * x)
*/

Note:

  • Duration in milliseconds (1000ms = 1s)
  • Second script uses the cos function. Example curve:

enter image description here

3# Simple scrolling library on Github

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJasperView Question on Stackoverflow
Solution 1 - JavascriptRobbendebieneView Answer on Stackoverflow