<div class="container">
<div id="top">
<a href="#bottom">To Bottom</a>
</div>
<div class="box"></div>
<div id="bottom">
<a href="#top">To Top</a>
</div>
</div>
html {
scroll-behavior: smooth;
}
body {
margin: 0;
font: 16px 'Segoe UI', Arial, Helvetica, sans-serif;
}
.container {
position: relative;
width: 100%;
height: 400vh;
}
.box {
position: fixed;
top: calc(50% - 100px);
left: 0;
width: 200px;
height: 200px;
background: tomato;
transform: translateX(calc(1px * var(--offset)));
}
#top,
#bottom {
position: absolute;
left: 0;
right: 0;
padding: 10px;
text-align: center;
}
#top {
top: 0;
}
#bottom {
bottom: 0;
}
const box = document.querySelector('.box');
let rect = document.body.getBoundingClientRect();
const normalize = (min, max, value) => {
return (value - min) / (max - min);
};
const lerp = (min, max, value) => {
return (1 - value) * min + value * max;
};
const map = (minSource, maxSource, minTarget, maxTarget, value) => {
return lerp(minTarget, maxTarget, normalize(minSource, maxSource, value));
};
const update = () => {
box.style.setProperty('--offset', map(0, rect.height - innerHeight, 0, rect.width - 200, scrollY));
};
window.addEventListener('scroll', update);
window.addEventListener('resize', () => {
rect = document.body.getBoundingClientRect();
update();
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.