Loading video...

Video Failed to Load

Go Home

Animated img carousel 🤙 Use CSS trig functions to get radius and layout images as a cylinder 🤓 Use scroll animation to rotate the cylinder 📜 :root { --a: calc((360 / var(--total)) * 1deg); --r: calc((var(--item-width) / sin(var(--a))) * -1); } Explained 👇

348,300 views • 2 years ago •via X (Twitter)

10 Comments

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

1st trick: Create two lists. One to drive the animation, and one for the images You can see It when you enable "debug" The controlling list has a scroll-timeline hoisted with timeline-scope ul.controller { scroll-timeline: --controller } :root { timeline-scope: --controller }

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

2nd trick: Create the cylinder layout using CSS trig functions :root { --a: calc((360 / var(--total)) * 1deg); --item-width: clamp(100px, 10vmin, 8rem); --r: calc((var(--item-width) / sin(var(--a))) * -1); } li:nth-of-type(3) { --index: 3; } li { transform: rotateY(calc((var(--a) * var(--index)))) translate3d(0, 0, calc(var(--r) * -1)); } Don't forget the transform-style: preserve-3d! 🤙

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

The last trick is to animate that rotate. Rotate the list on the y-axis with the hoisted scroll-timeline main{ timeline-scope: --controller;} .controller{ scroll-timeline: --controller inline;} .carousel { animation: spin; animation-timeline: --scroller;} @​keyframes spin {to:{rotate: y 360deg;}}

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

Here's the @CodePen link! 🚀 It will do a better job of explaining what's happening 😅 There are a bunch of little tricks in this one Love how CSS Math can do things like layout with ease and how easy scroll animations adapt ⭐️

arbie's profile picture
arbie2 years ago

Umm… but can you do this? 🤔 Anyway, thanks for always sharing dope stuff!

Michael Schiano's profile picture
Michael Schiano2 years ago

Wait what’s that config tool you’re using?

Rifandani ⚛️'s profile picture
Rifandani ⚛️2 years ago

Bro is PhD in CSS

Kevin Grajeda's profile picture
Kevin Grajeda2 years ago

You never disappoint

hrvy's profile picture
hrvy2 years ago

This is so freaking nice dude.

jhey ▲🐻🎈's profile picture
jhey ▲🐻🎈2 years ago

sin() is a trigonometric function You need to have a way to calculate the radius based on using sin() with the inner angle and the variable width It updates responsively with changes to number of items or size of items because it will recalculate via the custom property

Related Videos

CSS Tip! 🚥 You can create these trending expanding scroll indicators with scroll-driven animations and flex 🤙 .indicator { animation: grow; animation-range: contain calc(50% - var(--size)...; animation-timeline: var(--card); } @​keyframes grow { 50% { flex: 3; }} What's the trick? Put the indicators in a container using flex layout and set a width larger than the number of indicators 😉 .indicators { aspect-ratio: 7 / 1; display: flex; } Importantly, set no gap 🤏 To mimic the gap set a transparent border on each indicator and set the background using padding-box .indicator { background: linear-gradient(#​fff, #​fff) padding-box; border-radius: 50px; border: 4px solid transparent; } Now for the animation. You want to create a view-timeline for each card that moves across 🤙 li:nth-of-type(1) { view-timeline: --one inline; } li:nth-of-type(2) { view-timeline: --two inline; } Make sure they use the inline axis too! The trick is hoisting these view-timeline so the indicators can use them with timeline-scope 👀 .track { timeline-scope: --one, --two, ...; } All that's left is for you to create the animation piece using some calc with the card size ⚡️ .indicator { --size: calc(var(--card-width) * 0.9); animation: grow both linear; animation-range: contain calc(50% - var(--size)) contain calc(50% + var(--size)); } .indicator:nth-of-type(1) { animation-timeline: --one; } .indicator:nth-of-type(2) { animation-timeline: --two; } @​keyframes grow { 50% { flex: 3; }} And there you have it, responsive scroll indicators using CSS scroll-driven animations 😎 Sprinkle a little JavaScript to make them clickable and scroll the the right card ✨ const shift = (event) => { if (event​.target.tagName === "BUTTON") { const index = [...event.target.parentNode.children].indexOf(event​.target); const item = document.querySelector(`li:nth-of-type(${index + 1})`); item.scrollIntoView({ behavior: "smooth", inline: "center" }); } }; As always, any questions or suggestions, let me know. I've put a JavaScript fallback in to use GSAP in browsers that don't have scroll-driven animations 🫶 CodePen.IO link below! 👇

jhey ʕ•ᴥ•ʔ

575,457 views • 2 years ago