<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<style>
.blocks {
max-width: 60em;
width: 100%;
height: 200em;
display: flex;
margin: 20em auto;
}
.block {
background: linear-gradient(#f1f1f1 50%, #212121 0);
background-size: 100% 20em;
flex: auto;
margin: .1em;
will-change: transform;
}
</style>
<div class="blocks">
<div class="block" data-delay="6000"></div>
<div class="block" data-delay="2000"></div>
<div class="block" data-delay="4000"></div>
<div class="block" data-delay="9000"></div>
</div>
<script>
{
let y0 = 0;
let t0 = performance.now();
let speed = 0;
let blocks = document.querySelectorAll(".block");
let delay = Symbol.for("delay");
for(let block of blocks)
block[delay] = +block.dataset.delay || 1000;
let render = () => {
let y = document.body.scrollTop;
let t = performance.now();
let dy = y - y0;
let dt = t - t0;
if(dt < 16) return;
y0 = y;
t0 = t;
speed = .9 * speed - 0.000405 * dy / dt;
for(let block of blocks) {
block.style.transform = `translateY(${(-speed * block[delay]).toFixed(4)}px)`;
}
};
let main = () => {
render();
requestAnimationFrame(main);
};
main();
}
</script>
</body>
</html>