Skip to content

Instantly share code, notes, and snippets.

@git2358
Created May 19, 2020 05:36
Show Gist options
  • Select an option

  • Save git2358/eed0c0fb33e1c8ccf61a026502e95277 to your computer and use it in GitHub Desktop.

Select an option

Save git2358/eed0c0fb33e1c8ccf61a026502e95277 to your computer and use it in GitHub Desktop.
Smooth card scrolling interaction! ✨
<!--
Inspired by @MengTo on Twitter
https://twitter.com/MengTo/status/1260300550953934853
HTML is added through JS, no framework is used!
-->
document.body.innerHTML += `
<div style="height: 16px"></div>
`;
for (let i = 0; i < 10; i += 1) {
document.body.innerHTML += `
<div class="box"><div>
<svg preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320">
<defs>
<linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#f079ba"/>
<stop offset="100%" stop-color="#e34a82"/>
</linearGradient>
</defs>
<path fill="url(#linear)" fill-opacity="1" d="M0,224L60,208C120,192,240,160,360,165.3C480,171,600,213,720,197.3C840,181,960,107,1080,74.7C1200,43,1320,53,1380,58.7L1440,64L1440,320L1380,320C1320,320,1200,320,1080,320C960,320,840,320,720,320C600,320,480,320,360,320C240,320,120,320,60,320L0,320Z"></path>
</svg>
<div>Bank</div>
<div class="content">
<div>
<div class="label">Card Holder name</div>
<div class="value">Colin van Eenige</div>
</div>
<div>
<div class="label">Expiry Date</div>
<div class="value value-right">05/25</div>
</div>
</div>
</div></div>
`;
}
requestAnimationFrame(() => {
const boxes = document.querySelectorAll(".box");
function getIntersectionRatio(i) {
const a = [window.scrollY, window.scrollY + window.innerHeight];
const b = [boxes[i].offsetTop, boxes[i].offsetTop + boxes[i].clientHeight];
const max = Math.max(a[0], b[0]);
const min = Math.min(a[1], b[1]);
return Math.max(0, (min - max) / (b[1] - b[0]));
}
function onScroll() {
const boxes = document.querySelectorAll(".box");
for (let i = 0; i < boxes.length; i += 1) {
const intersection = getIntersectionRatio(i);
const top = boxes[i].offsetTop - window.pageYOffset < 0;
boxes[i].firstChild.style.cssText = `
transform-origin: ${top ? "center center" : "top center"};
position: ${top ? "fixed" : "absolute"};
transform: scale(${intersection});
opacity: ${intersection};
`;
}
requestAnimationFrame(onScroll);
}
onScroll();
});
// Option with less CPU usage, but also less FPS / smooth
// window.addEventListener('scroll', onScroll);
body {
margin: 0;
font-size: 18px;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
font-style: normal;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
margin: 0;
letter-spacing: 0.05em;
}
* {
position: relative;
box-sizing: border-box;
}
.box {
width: 400px;
height: 200px;
color: white;
margin: 0 auto;
margin-bottom: 24px;
}
.box > div {
display: flex;
position: absolute;
top: 0;
width: 400px;
height: 200px;
background: linear-gradient(220deg, #3d45b1, #844efc);
justify-content: space-between;
flex-direction: column;
padding: 16px;
border-radius: 16px;
box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.2);
transform-origin: top center;
will-change: transform;
overflow: hidden;
}
.content {
display: flex;
justify-content: space-between;
}
.label {
font-weight: bold;
font-size: 12px;
margin-bottom: 6px;
}
.value-right {
text-align: right;
}
svg {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment