<div id="container">
<div id="box"></div>
<div id="content"></div>
</div>
<div id="display">0</div>
#container {
width: 300px;
height: 100px;
overflow-y: scroll;
position: relative;
border: 1px solid black;
}
#content {
height: 800px;
}
#box {
width: 20px;
height: 20px;
background: red;
position: absolute;
}
const container = document.getElementById('container');
const box = document.getElementById('box');
const display = document.getElementById('display');
const speed = 1;
let current = 0;
let animationId = null;
const minDuration = 1;
const maxDuration = 500;
function lerp(start, end, t) {
return start + (end - start) * t;
}
container.addEventListener('scroll', () => {
if (animationId) cancelAnimationFrame(animationId);
const target = container.scrollTop;
const start = current;
const startTime = performance.now();
const distance = Math.abs(target - start);
const duration = Math.min(Math.max(distance * speed, minDuration), maxDuration);
function animate() {
const progress = Math.min((performance.now() - startTime) / duration, 1);
current = lerp(start, target, progress);
box.style.top = current + 'px';
display.textContent = Math.round(current);
if (progress < 1) {
animationId = requestAnimationFrame(animate);
}
}
animate();
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.