Some sites that I found amazing inside Awwwards, are using this method from shimming the scroll of their webpage.
requestAnimationFrame
is special function for your animation to work, basically you use loop to make changes every few milliseconds. So it’s basic API for use with animation, whether that be DOM-based styling changes, canvas or WebGL.
Supporting requestAnimationFrame
As we know, browsers are different, so we have to set some fallback for requestAnimationFrame.
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller
// fixes from Paul Irish and Tino Zijdel
(function() {
var lastTime = 0;
// checking website vendors that has their own requestAnimationFrame
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
|| window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());
Code above is more like checking and give the robust solution of requestAnimationFrame
and cancelAnimationFrame
fallback.
The basic HTML structure
<html>
<!-- ... -->
<body>
<!-- #app will be used for wrapper of your website content -->
<div id="app">
<!-- content will be here -->
</div>
</body>
<!-- ... -->
</html>
and the Javascript
document.addEventListener('DOMContentLoaded', function() {
// get the #app
let wrap = document.getElementById('app');
// set the styles of #app
wrap.style.position = 'fixed';
wrap.style.width = '100%';
wrap.style.top = '0';
wrap.style.left = '0';
// initialize #app position to the window
// on top of page
wrap.style.transform = 'translateY(0)'; // you can also use top
});
From above code, we fixed the position of #app
div, it's because actually we will simulate the scroll animation using CSS transform: translateY()
or top
animation;
Getting the scroll progress
Our
#app
has fixed position which means the body doesn’t care about its height anymore, this will deactivatescroll
event and remove scrollbar from browser.
So we have to create an empty div
which has the height of the #app
.
let fakeDiv = document.createElement('div');
fakeDiv.style.height = wrap.clientHeight + 'px';
document.body.appendChild(fakeDiv);
Updating the scroll progress
let update = function () {
window.requestAnimationFrame(update);
if (Math.abs(scrollTop - tweened) > 0) {
// you can change `.072` for the acceleration of scroll
let top = tweened += .072 * (scrollTop - tweened), // update value of Y translation
wt = wrap.style.transform = `translateY(${(top * -1)}px)`;
}
};
// optional function for adding event
let listen = function (el, on, fn) {
(el.addEventListener || (on = 'on' + on) && el.attachEvent)(on, fn, false);
};
let scroll = function () {
scrollTop = Math.max(0, document.documentElement.scrollTop || window.pageYOffset || 0);
};
listen(window, 'scroll', scroll);
// trigger the update function
update();
Note: you need to update the height of the
fake scroll div
when resize the page
That's it. Demo can be accessed here.
And here's the complete code.
Thank you for taking time to read this article.
Happy coding 😊
Top comments (0)