Video wird geladen...

Video konnte nicht geladen werden

Zur Startseite

Future CSS Tip! ๐Ÿ You can create this Apple-style photo scroller by combining CSS scroll-driven animations and CSS scroll-snap ๐Ÿ˜ Peep those changing captions ๐Ÿ‘€ No JS! img { animation: highlight both linear; animation-timeline: view(inline); ๐Ÿ‘ˆ Horizontal animation-range: cover 0% cover 50%; ๐Ÿ‘ˆ Finish } @ keyframes highlight {...

234,561 Aufrufe โ€ข vor 2 Jahren โ€ขvia X (Twitter)

11 Kommentare

Profilbild von jhey โ–ฒ๐Ÿป๐ŸŽˆ
jhey โ–ฒ๐Ÿป๐ŸŽˆvor 2 Jahren

Here's that @CodePen link! ๐Ÿš€ You need to be in Chrome to see this in action ๐Ÿ“œ But, how cool? CSS only list animations that could work as a progressive enhancement โœจ If they aren't supported, your user still gets a good experience ๐Ÿ™Œ

Profilbild von jhey โ–ฒ๐Ÿป๐ŸŽˆ
jhey โ–ฒ๐Ÿป๐ŸŽˆvor 2 Jahren

And here's the original piece of UI from the iPhone 15 Pro page ๐Ÿค™ The CodePen demo isn't quite as "polished". But, it's proving the concept of what we can achieve ๐Ÿ”ฅ The iPhone page uses JavaScript to update the transform matrix of the images via inline styles as you scroll. Think if you mess with the timing a little, it could be spot-on in the CSS-only version ๐Ÿ’ฏ Maybe using some of the linear() stuff from recent weeks ๐Ÿค”

Profilbild von Tim Okonkwo โš›๏ธ
Tim Okonkwo โš›๏ธvor 2 Jahren

This guy makes me feel I didnโ€™t learn CSS ๐Ÿ˜‚

Profilbild von jhey โ–ฒ๐Ÿป๐ŸŽˆ
jhey โ–ฒ๐Ÿป๐ŸŽˆvor 2 Jahren

Haha โ€“ You now CSS ๐Ÿ˜‰ But, it's constantly evolving.

Profilbild von Oscar Cornejo
Oscar Cornejovor 2 Jahren

๐Ÿ‘๐Ÿผ๐Ÿ‘๐Ÿผ๐Ÿ™Œ๐Ÿผ

Profilbild von jhey โ–ฒ๐Ÿป๐ŸŽˆ
jhey โ–ฒ๐Ÿป๐ŸŽˆvor 2 Jahren

Thanks Oscar ๐Ÿ™

Profilbild von ๐Ÿ‘จโ€๐Ÿ’ป damir.fun ๐Ÿ˜Ž
๐Ÿ‘จโ€๐Ÿ’ป damir.fun ๐Ÿ˜Žvor 2 Jahren

CSS scroll snap is insanely powerful

Profilbild von jhey โ–ฒ๐Ÿป๐ŸŽˆ
jhey โ–ฒ๐Ÿป๐ŸŽˆvor 2 Jahren

The undercover goat ๐Ÿ๐Ÿ˜…

Profilbild von Nikola Lakovic
Nikola Lakovicvor 2 Jahren

๐Ÿคฏ

Profilbild von Helios Dev
Helios Devvor 2 Jahren

Sick! Would there be any possibility to start them from display none as well? Could create a โ€œlazy loaderโ€ purely with CSS, as I recall the browser doesnโ€™t load resources such as images when itโ€™s set to display: none. Maybe in combination with :has and :visible.

Profilbild von jhey โ–ฒ๐Ÿป๐ŸŽˆ
jhey โ–ฒ๐Ÿป๐ŸŽˆvor 2 Jahren

I need to revisit this demo today ๐Ÿคž Wanted to add an intro animation to it too. One trick here is that it's all the same image for this purpose but cropped with object-view-box. Perhaps, animating stepped with display and using a preload perhaps ๐Ÿค”That's off the top of my head

ร„hnliche Videos

CSS Trick! โšก๏ธ You can use scroll-driven animation with background-attachment to create a dynamic glowing card scroller without JS ๐Ÿ”ฅ section { animation:vibe; animation-timeline:--list; } @โ€‹keyframes vibe { to{--hue:320;}} .glow {background: hsl(var(--hue) 80% 50%);} Here's how! ๐Ÿค™ You can use the background-attachment trick used in other glow card demos ๐Ÿ˜Ž article { background-attachment: fixed; } The difference here is that you aren't going to update the fixed background position with your pointer this time. It can remain fixed. The magic part is that as you scroll, the background will leave the card that's leaving and enter the card that's entering โœจ For the extra background glow, you can use a fixed pseudo element on the list container itself ๐Ÿ’ช Once that's in place, you're only task is to change the color of the background as you scroll ๐Ÿค” Create a custom property declaration for the --hue @โ€‹property --base { inherits: true; syntax: ' '; initial-value: 0; } Then create an animation that updates this value @โ€‹keyframes accent { to { --hue: 320; }} The last piece is hooking it up to scroll and there is a little trick in here ๐Ÿ‘€ First, you need an inline scroll-timeline on the list ul { scroll-timeline: --list inline; } Then you can use timeline-scope to hoist that scroll-timeline up so a parent can use it. You then animate the custom property on this element and let the value cascade down to the places that need it ๐Ÿ”ฅ section { timeline-scope: --list; animation: accent both linear; animation-timeline: --list; } For example, the glow uses the --hue this way [data-glow] { background-image: radial-gradient( 150px 150px at 50% 50%, hsl(var(--hue) 100% 70% / 0.25), transparent ); } Lastly, scroll-snap is optional of course but plays nice with the scroll-driven animation demos โœจ The key for that is ul { scroll-snap-type: x mandatory; } li { scroll-snap-align: center; } That's it! Pretty fun trick to play with! ๐Ÿค“ Any questions, let me know! Should we add it to the video walkthrough list? CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

116,625 Aufrufe โ€ข vor 2 Jahren

CSS Tip! ๐Ÿณ You can add little details like this scale down on scroll effect with scroll-driven animations and some sticky positioning ๐Ÿค™ section { animation: scale-down; animation-timeline: view(); animation-range: exit; } @โ€‹keyframes scale-down { to { scale 0.8; } ] In this smaller example, you can lean into using the position to drive an animation that scales itself down as it leaves the viewport (Seen on the Apple Vision Pro site ๐Ÿ) The nice thing here is that if you don't have scroll-driven animations, the user still gets a good experience โœจ So how do you do it? There isn't much to it header { transform-origin: 50% 0%; animation: scale-down both ease-in; animation-timeline: view(); animation-range: exit; view-timeline: --header; } @โ€‹keyframes scale-down { to { scale: 0.8 0.8; } } That's it. The layout makes use of position: sticky so that the element stays in the shot whilst you scroll the page. As it leaves the page, it scales down inside the ๐Ÿซถ The other smol animation here is fading the overlay on the video out ๐Ÿ˜Ž Real easy. You may notice the view-timeline you defined above for the ๐Ÿ‘€ header { view-timeline: --header; } You have a pseudoelement on the text content of the header that lives inside a header > section::before { background: hsl(0 0% 0% / 0.75); opacity: 1; animation: fade both linear; animation-timeline: --header; animation-range: exit-crossing 0% exit 0%; } @โ€‹keyframes fade { to { opacity: 0; } } You use a slightly smaller range on this with exit-crossing to fade it out before you start the scale down animation ๐Ÿค That's it! Thought this smaller example would be easier to grok for people ๐Ÿ™ It's also covered with JavaScript if you really want it for your sites ๐Ÿค™ CodePen.IO link below ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

146,270 Aufrufe โ€ข vor 2 Jahren

CSS Trick ๐Ÿค™ You can use scroll-driven animations on the inline axis to create list animations like in these cards ๐Ÿซถ article { animation: vibe; animation-timeline: view(inline); animation-range: cover 40% cover 60%; } @โ€‹keyframes vibe { 50% { scale: 1; filter: grayscale(0); }} Here you use a view() timeline with the inline axis set inside the function. This means you can hook into the horizontal scroll position of an element inside its scroller ๐Ÿ™Œ In this demo, you set a default smaller scale and make each card grayscale ๐Ÿค article { scale: 0.8; filter: grayscale(1); } Then the animation happens as each card enters from the right at 0% and leaves to the left at 100% ๐ŸŽž๏ธ 50% is the halfway point and in your keyframes you make each card grow and saturate at that point before returning to its original state โœจ scroll-snap provides a nice look-and-feel here and on mobile ๐Ÿซฐ It's really as straightforward as that but made so much easier with a few lines of CSS ๐Ÿ’™ For the parallax effect, you can animate a background-position on the card or the object-position on an img depending on what you go with ๐Ÿค™ Lastly, you can use this today with progressive enhancement by wrapping your scroll-driven animation code in @โ€‹supports and @โ€‹media โšก๏ธ Users without support still get a decent experience! CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

465,403 Aufrufe โ€ข vor 2 Jahren

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,634 Aufrufe โ€ข vor 2 Jahren

CSS Tip! โœจ You can create these parallax effects and image cross-fades with scroll-driven animations ๐Ÿค™ img { animation: fade; animation-timeline: view(); mix-blend-mode: plus-lighter } img:last-of-type { animation-direction: reverse; } @โ€‹keyframes fade { to { opacity: 0; }} This one's fun! ๐Ÿ˜ The trick with the cross-fading image is to make use of one animation that runs at the same time on two images inside a container. You use the same animation, animation-timeline, and animation-range. But, you use animation-direction: reverse on one of the images so they go in the opposite direction ๐Ÿซถ The use of mix-blend-mode: plus-lighter; produces a better cross-fade result ๐Ÿ’ฏ A viewTimeline (view()) works because you know that both images are the same height. The range you can use is img { animation-timeline: view(); animation-range: cover 45% cover 55%; } That means when the image has covered 45% of the scrollport (In this case, the window), start the animation. And finish when it has covered 55% ๐ŸŽฌ How about the slight parallax? This is a trick with calc(). You know the top of the small image and the big image line up. And you can do this by absolutely placing the caption outside of the small image. The trick is to translate the small image by a distance so it lines up with the bottom of the big image. You can do that like this :root { --catch-up: calc( var(--big-height) - var(--small-height) ); } @โ€‹keyframes move { to { translate: 0 var(--catch-up); }} Then drive that animation with a scroll-driven animation using the container of both images as the driver ๐Ÿค™ /* section contains both images */ section { view-timeline: --container; } .img-fader { animation: catch-up both linear; animation-timeline: --container; animation-range: 50vh calc(100vh + (var(--big-height) * 0.25)); } That's it! Scroll-driven image cross-fading and parallax effects without any JavaScript. This demo will work in all browsers as there is some JavaScript in place where the API isn't supported ๐Ÿค™ To do that, it uses GSAP ScrollTrigger ๐Ÿ† As always, any questions, requests, etc. hit me up! ๐Ÿค™ CodePen.IO link below ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

242,205 Aufrufe โ€ข vor 2 Jahren

CSS Tip! ๐Ÿ“œ You can use scroll-driven animations to progressively enhance collapsing a floating call to action ๐Ÿค .cta { animation: shrink; animation-timeline: scroll(); animation-range: 0 100px; } @โ€‹keyframes shrink { to { width: 48px; } } That's the gist of it. Use the body scroll position with animation-timeline: scroll(). Define the animation-range as when you have scrolled 100px. There's a little more though ๐Ÿค“ That would "scrub" the width animation. Ideally, you want to trigger that animation. You could animate a custom property with steps() timing and use that to define the width โœจ @โ€‹property --scrub { syntax: ' '; inherits: true; initial-value: 0; } body { animation: scrub both steps(1, end); animation-timeline: scroll(); animation-range: 0 100px; } Then transition the --scrub property on the CTA and use it for the width ๐Ÿค™ .cta { transition: --scrub 0.2s; width: calc(48px + (120px * (1 - (var(--scrub) / 100)))); } Other animations are a matter of preference and timing. For example, you could then make the hand wave, scale down the size, and then slide a gradient across ๐Ÿ˜‰ They have the same structure and technique as the original concept. Waving the hand? ๐Ÿ‘‹ Run it twice, offset the transform-origin. .hand { animation: wave both linear 2; animation-timeline: scroll(); animation-range: 30vh 50vh; transform-origin: 65% 75%; } @โ€‹keyframes wave { 50% { rotate: 20deg; } } How's it progressively enhanced? Wrap everything in a @โ€‹supports query and a @โ€‹media query. If there isn't support, users still get a good experience. It's a floating action button that's circular and already collapsed ๐Ÿค™ @โ€‹supports(animation-timeline: scroll()) { @โ€‹media(prefers-reduced-motion: no-preference) {...} } Definitely have a play with the code. Amazing what we're going to be able to do with CSS alone! ๐Ÿ”ฅ CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

177,902 Aufrufe โ€ข vor 2 Jahren

CSS Tip! ๐Ÿฌ You can create a CSS-only sticky CTA using position: sticky or scroll-driven animations ๐Ÿค™ .cta { position: sticky; margin-top: 110vh; bottom: 2rem; /* ๐Ÿ‘ˆ Stick! */ } This is one way ๐Ÿ‘€ This first way relies on you setting a layout on the body and putting the CTA in a zero-space part of the layout body { display: grid; grid-template-columns: auto 0; } The children of the body are an element with your content and then the CTA. You could also use display:flex too. .content { flex: 1 0 100%; } .cta { place-self: end; } As you scroll the body, the CTA comes into view and sticks in position ๐Ÿ™Œ That's one way. If you want to take it further and do something like flip between showing or not, maybe scale it up, or add some special easing, etc. an animation is another way ๐Ÿ“œ First, change the styles for your CTA. Note the translate property that's powered by a custom property .cta { position: fixed; bottom: 2rem; right: 2rem; translate: 0 calc(20vh - (var(--show) * 20vh)); transition: translate 0.875s var(--elastic); } Next you need a custom property that you're going to animate @โ€‹property --show { inherits: true; initial-value: 0; syntax: ' '; } Lastly, you animate this value on the body. As the property value changes, the value will trickle down to the CTA @โ€‹supports (animation-timeline: scroll()) { body { animation: show-cta both steps(1); animation-timeline: scroll(root); animation-range: 0 10vh; } @โ€‹keyframes show-cta { to { --show: 1; } } } Using @โ€‹supports you can use this as a progressive enhancement. If scroll-driven animations are supported, use them. Otherwise fallback to using position: sticky ๐Ÿค™ That's it! As always, any questions or requests, hit me up! ๐Ÿ™ CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

133,020 Aufrufe โ€ข vor 2 Jahren

CSS Tip! ๐ŸŽ  You can create a responsive infinite marquee animation with container queries and no duplicate items ๐Ÿค™ li{ animation: slide; } @โ€‹keyframes slide { to { translate: 0% calc(var(--i) * -100%);}} The trick is animating the items, not the list ๐Ÿ˜Ž More tricks ๐Ÿ‘‡ To get this one working, you need to animate the items and not the list (Watch the video first?). Each item needs to know its row index (--i) in the list and the parent needs to know how many rows are in the list: ul { --count: 12; } li:nth-of-type(1), li:nth-of-type(2) { --i: 0; } li:nth-of-type(3), li:nth-of-type(4) { --i: 1; } Once you have that, translate each item based on its row index in the list li { translate: 0% calc((var(--count) - var(--i)) * 100%); } Now for the animation. The key here is that each row has an animation-delay calculated from its index (--i). That number is offset to make it negative so the animation start is offset โœจ ul { --duration: 10s; } li { --delay: calc((var(--duration) / var(--count)) * (var(--i) - 8)); animation: slide var(--duration) var(--delay) infinite linear; } Make sure to wrap that animation in: @โ€‹media (prefers-reduced-motion: no-preference) { ... } Lastly, the fun parts! ๐Ÿค“ To create the "vignette" mask. Use a layered mask on the container ๐Ÿ˜ท .scene { --buff: 3rem; height: 100%; width: 100%; mask: linear-gradient(transparent, white var(--buff) calc(100% - var(--buff)), transparent), linear-gradient(90deg, transparent, white var(--buff) calc(100% - var(--buff)), transparent); mask-composite: intersect; } To create the 3D skewed effect, use a chained transform (Try toggling it in the demo โšก๏ธ): .grid { transform: rotateX(20deg) rotateZ(-20deg) skewX(20deg); } As for the responsive part, use container queries! ๐Ÿ”ฅ article { container-type: inline-size; } When the article (card) is narrower than 400px update the grid and animation settings ๐Ÿค™ Double the rows means double the duration! @โ€‹container (width < 400px) { .grid { --count: 12; grid-template-columns: 1fr; } li:nth-of-type(1) { --i: 0; } li:nth-of-type(2) { --i: 1; } li:nth-of-type(3) { --i: 2; } li:nth-of-type(4) { --i: 3; } li { --duration: 20s; } } CSS has the magic to be able to update those animations at runtime based on your custom property values ๐Ÿ˜Ž An added bonus in this demo is that it doesn't require any JavaScript at all, for any of it ๐Ÿคฏ We can use CSS :has() for those toggles that update the styles, even the theme toggle! ๐Ÿซถ Any questions, let me know! Make sure to check out the video. Will do a walkthrough one to follow-up ๐Ÿค™ CodePen.IO link below! ๐Ÿ‘‡

jhey ส•โ€ขแดฅโ€ขส”

542,467 Aufrufe โ€ข vor 2 Jahren