JSFiddle - React, Tailwind, and code Playground
https://old.reddit.com/r/webdev/comments/9w39r4/how_would_something_like_the_card_scroll_even_be/
by alexb
HTML
<div class="cards">
<div class="card card-gray"></div>
<div class="card card-blue"></div>
<div class="card card-pink"></div>
</div>
<input type="range" value="0" max="1000">
CSS
.cards {
height: 300px;
padding: 50px;
perspective: 800px;
}
.card {
border-radius: 25px;
height: 250px;
width: 400px;
position: absolute;
}
.card-gray {
background-image: radial-gradient(farthest-corner at top left, #808080, #404040);
}
.card-blue {
background-image: radial-gradient(farthest-corner at top left, hsla(210, 74%, 50%), hsla(210, 74%, 25%));
}
.card-pink {
background-image: radial-gradient(farthest-corner at top left, hsla(350, 95%, 90%), hsla(350, 100%, 75%));
}
JavaScript
const range = document.querySelector('[type=range]');
const allCards = document.querySelectorAll('.card');
const offscreenCards = [...allCards].slice(0, allCards.length - 1);
const mainCard = allCards[allCards.length - 1];
function update() {
const progress = range.value / range.max;
allCards.forEach(card => {
card.style.transform = `rotateX(${-40 * progress}deg)`;
});
for (let i = 0; i < offscreenCards.length; i++) {
const s = offscreenCards.length;
const p = clamp(0, 1, progress * s - (s - i - 1));
offscreenCards[i].style.top = `${lerp(-500 + 100/s*i, 50 + 100/s*i, p)}px`;
offscreenCards[i].style.opacity = p;
}
mainCard.style.top = `${lerp(50, 150, clamp(0, 1, progress * offscreenCards.length))}px`;
}
range.addEventListener('input', update)
update();
function lerp(min, max, val) {
return min + (max - min) * val;
}
function clamp(min, max, val) {
return Math.min(max, Math.max(min, val));
}