skip to content

CSS-Only Scroll-Driven Animation and Other Impossible Things

Wait, you can’t do scroll-driven animation with just CSS, right? Bramus will show us that not only is it possible, but there’s even more that CSS can do these days.

Full Transcript

Click to toggle the visibility of the transcript

Captions provided by White Coat Captioning ( Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.

JASON: Hello, everyone. And welcome to another episode of Learn with Jason. Today on the show, we've brought on Bramus. How are you doing?

BRAMUS: I'm doing great. How are you, Jason?

JASON: How do you like that pronunciation? I'm going to get it just right.

BRAMUS: I have a few pronunciations, I say Bramus with the long A, and in English, it becomes Bramus or Bromise --

JASON: It's unfortunate. I have the American problem of being completely unable to roll an R. Everything sounds like I've got marbles in my mouth.

BRAMUS: The good thing is I work mostly with American and English-speaking people. I'm used to it, no worries.

JASON: You're used to just having your name completely butchered.


JASON: I apologize. So, all right. So, I am so excite to have you on the show. This is gonna be a lot of fun. We're talking about one of my favorite things in the entire world which is playing around with CSS. And I just can't wait. But before we talk about that, let's talk a little bit about you. For folks who aren't familiar with you and your work, do you want to give us a bit of a background on yourself.

BRAMUS: I'm Bramus, or Bramus, it depends. And I'm a Chrome developer relations engineer at Google. I'm involved mainly with CSS and web UI. That's all of the new CSS stuff that is coming. But also some new web UI stuff, for example. The select list item. The details element that's getting like some love. And it's gonna ship like soonish-hopefully. So, yeah. That's what I'm concerned with. And before that, I always -- I was a web developer in the past 20-ish years I have been doing web development, backend, frontend, whatnot. But my passion was always CSS. So, yeah. That's what eventually got me in at Google and that's what I'm doing now as my day-to-day job.

JASON: I love it. I can't imagine something I would enjoy more than being able to collect a paycheck to play with CSS and like stress test it and make it better for the platform. So, you are -- you're doing one of my dream jobs over there. So, I'm actually -- I'm curious because I feel like -- and this is not me trying to start a debate. Because I -- I know this is kind of a touchy topic. But like there's that sort of pervasive belief that CSS is somehow less-than when it comes to writing other programming languages. And that's never sat right with me because I feel like of all the things that have challenged me, getting CSS to do the thing that I see in my head is -- is so much more of a programming exercise to me than when I'm trying to, you know, make logic work in JavaScript or something like that. So, as you've sort of made this your career, how -- how deep does the rabbit hole go on CSS? You have been doing it for years now. Like do you feel like you're done? You've learned it all? Or like how much further is there to go?

BRAMUS: I feel like I need to learn -- I still need to learn like a ton of stuff. It's only whether you start like digging into certain things. And now also part of my job. That you start learning all like the little details and intricacies about something. Like the cascade, for example. It's part of name, right? Cascading style sheets. It's on the when you start digging deep, oh, there's this little detail over here. Oh, that's how it works. Before I was taught, cascade, you have the origins and specificity with the numbers and that's it. Well, there's quite a lot to learn about it. And that's just that little part of CSS. Because CSS has exploded over the years with many new specs coming. Like Flexbox play out. If you transition, scroll animations. All the positioning things you can do. Yeah, it's a very, very deep rabbit hole to go into.

JASON: Yeah, absolutely. This is sort what have I have been noticing from myself at least is that I felt for a long time when I was younger that, you know, there was -- there was kind of like a point where you would be done learning something. Where you could learn it. And you would, you know, I don't know, hit the end of the manual or something and as long as you knew all the things in the manual, I'm finished. I know this forever now. And as reality set in, as I got deeper and deep entire my career, I just realized that even if you are the leading expert on a certain subject, there is still always one more thing to learn. And then when you learn that thing, it answer -- it opens a question. And then that's one more thing to learn and you just -- you can never really run out of things to learn or try. And as people, you know, use a thing, it evolves. And that's actually been one of the most fascinating things for me to watch is from the late '90s when I first became aware of the web and of building websites to the early 2000s when I started doing it professionally to today, CSS has gone from not existing to becoming something that was -- I would say rudimentary in the early 2000s. It was like, it does -- you know, it does enough. We can get some font changes, we can get some colors. To today we can do -- I saw somebody built a Morse code decoder in pure CSS. It absolutely melted my brain trying to figure out how it worked. And we're seeing stuff like, you know, people are building these incredible 3D models. Building unbelievable things. People like Lynn Fisher are doing CSS art. Full-blown oil painting lookalikes in CSS. And I saw some work from you when Una was on the show recently, she was showing me a bunch of scroll-driven animations that were built completely in CSS. And if you told me three years ago that you were going to try to build a CSS animation in pure CSS -- or a scroll-driven animation in pure CSS, I would assume that you didn't know how the web worked. There's no way. You can't do that. It's impossible. And yet here we are. And it's working. So, tell us a little bit about this. Like how -- I mean, first of all, like I kind of made an assumption that scroll-driven is the biggest thing you focused on. But like what are you finding to be the most exciting parts of CSS as its evolved over the last few years?

BRAMUS: The most exciting parts I think are the -- like the non-default uses of a certain technology. And like you've mentioned Lynn Fisher, you mentioned I paintings for example. And I see Jane is also in the chat. Like, for example, they launched the space toggle hack. It uses custom properties and it's like a switch you can flip on or off. And that invention, because it is an invention, led to many more other things that you can do with CSS. And that's -- that's so cool. Same thing with scroll over animations, for example. You've already mentioned it. But way to do way more than scroll-over animations. Maybe later in the show, maybe some uses for scroll-driven animation.

JASON: I have never heard of this space toggle. And now Jane, if you want to come teach me things, hit me up. I would love to learn about this invention. Okay. So, scrolling is kind of intrinsically an action that to me feels like it is outside of the style, right? But it does affect the way that the page looks because you're moving things up and down. And a huge part of CSS recently has been figuring out ways to manage transitions. Figuring out ways to do keyframe animations and -- and this is, you know, to me this has been a very interesting like where do you draw the line between what should and should not be in CSS? And so, you've been in this world for a while. Like how did this conversation go when the discussion about trying to get scroll triggers into CSS, like was it -- was it kind of a unanimous like, yeah, that makes sense? Or was there a lot of pushback, like, no, we shouldn't bring that sort of thing into the spec?

BRAMUS: So, the initial discussions on this predate my time at Google. Because I dug a bit like -- because now I have access to some internal docs. And like some of the earliest conversations date back to more than 5 years ago. Engineers already thinking about it at the time. And it was part of the Houdini effort. They wanted like an animation worklet to do something. Oh, yes, and you could attach it to scroll as well. And that kind of made the thing. But that little part went nowhere. That big chunk went nowhere. But the small part of scroll-driven animations. Like that idea continued to move on and be, yeah, get evolved. And like I think three years ago we had a working implementation using an @scrolltimeline rule. But it was working, that feels very un-CSSy. You can see, it was like a JavaScript-type of solution that was then transformed to, oh, we need to do this in CSS. Let's invent an @scroll timeline rule. It was a JavaScript to CSS translation. But it was working. You need to rewrite things. That's around the time when I joined Google. So, I have been part of the spec writing process and giving suggestions. Oh, maybe this should be easier and this should be done. Yeah. And we have it now. It shipped in Chrome 150, which is amazing, I think.

JASON: Yeah. And is this -- I guess as a like a first level setting, is this something that I can use cross-browser right now?

BRAMUS: So, the answer is "No." Because Chrome right now is the only browser to support it. Firefox, however, is working on implementation. That's very good news. Then WebKit, Safari, expressed their support for the API. Okay. We like this API. Or we can agree that it's useful. And maybe someday we'll implement it. That's basically what they are saying. So, it's no guarantee that we will have it this year or next year. Who knows? Time will tell.

JASON: Gotcha.

BRAMUS: It's only supported in Chrome. But all browser vendors are on board which is one very good thing. And then the other great thing about scroll-driven animations is I mostly I use them as a progressive enhancement. They are not essential to how the website should work. So, if my CSS doesn't load or my browser doesn't support scroll-driven animations, you still get to see the style thing, but it won't animate on scroll. And that's not that bad, I think.

JASON: Yeah. That makes sense. Okay. So, I realize -- I just jumped right into talking about the history of this. And I never actually asked you to define what it is. So, for somebody who is just hearing this term for the first time, what is a scroll-driven animation?

BRAMUS: The name kind of should say itself. But that's going to -- so, it's an animation driven by scroll. So, think of a CSS animation or one created using the web animations API. And when you use it, and you go to page, you have a web animation on there, or a CSS animation, it will load and start running. And the document timeline. So, when the page loads, document timeline starts at zero and then goes one second, two seconds, three seconds, and so on. And with scroll-driven animations, you say, hey, don't run this animation on the document timeline. But run it on a certain scroll timeline. And that means that if you are at the very top of your scroller, you are at zero percent progress. And if you scroll all the way to the end of your scroller, you are at 100% of your scroll process. So, your animation will move as you scroll up and down. Ergo the same, scroll-driven animation.

JASON: This is -- what I love about this is that it gives us this capability as Devs to have some -- like -- have an animation that's not just kind of playing on a loop. But that it's moving as the user moves. And if you go down the page a little bit and then back up, you know, the animation will kind of like go back and forth with you and we've seen this in like product demos, you know? Where you look at the classic like Apple marketing style page. Where if you scroll down the page, the computer spins into view and zooms? And zooms out. And previously, these were absolutely monstrous passage. Like they were huge, multiple, multiple mega bytes, tons of JavaScript. Part of that is because the images are enormous. You can't make the images small when they're that high res. Well, you can. But that's a different topic. But with that being said, a lot of it was dedicated to loading these big JavaScript libraries and then you have to do a lot of like observing the window and looking at where the user is. And it just -- it gets very heavy. And so, what you're saying is that with this scroll-driven animation, if I -- if I want to make one of those where I'm doing a product demo and got stuff spinning in and zooming out. I could do this on my -- I could do this on my own site without JavaScript now?

BRAMUS: Yeah, exactly.

JASON: Cool...

BRAMUS: The cool thing is because these scroll-driven animations, they work in conjunction with the existing CSS animations and web animations. And those animations already know how to run things on the compositor. So, off the main track. Which means that you will have more time for other JavaScript to run. Like you said before, you need to have like a scroll progress listener, which uses some blocking JavaScript. Then needs to take the scroll offset. Oh, yeah, you're this far into the page. That's this much percent. And so on. You no longer need that. Scroll-driven animations will take care of all of that for you, which is amazing.

JASON: And it also -- I can just picture a few things that have stopped me from doing really intense have animations in the past like responsive styling for it. And things that, you know, when you're doing it in JavaScript, you're like trying to re-implement features of CSS to make sure that it fits within the window, to make sure that it's visible. To make sure it's the right width, that the aspect ratio is not messed up. And if you're in CSS, if I'm animating a div, and I know that the thing inside of that div is sized properly, then I can -- I can just animate that thing and know that my CSS is going to apply to. And like I'm not trying to take my CSS out of the style sheet and into the animation tools like custom styling thing that I hope works the same way. And, you know -- and it really just -- it feels like kind of coming home as a -- as somebody who is building a lot of in my case very silly, but still fairly ambitious. Like I want to make something fun happen when you see this website. And I love that you can do so much more of this just using web standards. And I'm not loading. I love GSAP, no shade on it at all. But it's nice they only these GSAP for my really advanced ideas, as opposed to reaching for it when I want to do anything at all. Which sometimes feels a little heavy when I'm like, I wanted this to move from here to here when you scroll down the page. And I don't want to load GSAP to do that.

BRAMUS: Yeah. Because it taps into CSS. You can use -- it's just a bunch of properties and values that you set. But you can integrate into prefers reduce motion media query. Into another media query that says, hey, if the screen is very narrow, animated in a different way, it's all just in CSS that you can do it. Do note, I'm focusing on the CSS part here.

JASON: Sure.

BRAMUS: If you want, you can have it integrated with web animations API which is the JavaScript way of using the same mechanics. So, you can do both, but I prefer the CSS way.

JASON: Yeah. And I guess it's like another tool to have in the belt which is there's no better way to be than just prepared, right? If you know how all these things work you can choose the solution that's going to get what you want in the least amount of jank for the users, the least amount of ongoing effort. A good thing to learn and understand because, you know, especially these days, everything is expecting websites to do a lot. Where our expectations are getting really high for what a good website is. And what a good website feels like. So, these sorts of times being built into the browser. That's a big opportunity for us to level up without having to take that out of the performance budget or take that out of the -- the experience of users on less-performant devices. Because as you said, it's a progressive enhancement. If they don't have a device that supports these, it really big deal animations or whatever, we can detect that. We cannot run the animation and just show them a perfectly reasonably-looking -- like good-looking site that doesn't have stuff flying all over the screen. I just love that. It is wonderful.

BRAMUS: You want to see an example?

JASON: Absolutely I want to see an example. All right. Let me -- let me switch us over into the pair programming view here. Let me get this over here and then I'm gonna move this on to the screen. And there we go! All right. So, before -- before you start, I'm going to do a quick shoutout to our -- our sponsors and our live captioning. So, we've got White Coat Captioning, Amanda is with us here today doing the closed captioning for this show. If you want to see is that, just click that little closed caption button that's right down there. And that's made possible through our sponsors, Netlify and Vets Who Code, both kicking in to make this show more accessible to more people which I very much appreciate. We are talking to Bramus. What's the right place to send people if I want to point them to you on the web?

BRAMUS: Twitter or X, I should say. Sorry. Bramus is my username. And also, my website,

JASON: What a good website. That's a good domain. I love that.

BRAMUS: Thanks.

JASON: So, this is you. Let's find the scroll CSS -- what am I looking for? Is it not scroll behavior... I want...

BRAMUS: Well, you want a few properties. But maybe the easiest thing to do is go to


BRAMUS: Dot style. And they have like a full page with everything thereon. If you scroll, you already see scroll-driven animation. Did you see the mouse move as you scroll down.

JASON: Yeah. Look. As I'm moving up and down, it moves with me, right? It's not like a trigger once and then it's done. It's very much a part of the site. And these scrolling --

BRAMUS: And same with the cards, reveal themselves as you scroll.

JASON: I love it. All right.

BRAMUS: And so, the basic one that you want to check out there is the reading progress indicator. I think that's really good starting example.

JASON: Okay. So, you can see up here, we've got -- as we scroll down the page, it's showing how much of the page is left to read.

BRAMUS: Yep. exactly.

JASON: Which this was all the rage -- I think I saw three or four independent JavaScript libraries that got published. Hey, install this package to get a reading progress indicator at the top of your site. And now we can do this in CSS. And if I had to guess, I'm gonna take a wild guess, that building this particular interaction is something like ten lines of CSS.

BRAMUS: For the animation part, it's less. You need the positioning part. But yes. It's only a few lines of CSS.

JASON: Wonderful.

BRAMUS: That's the easy one. Go to the icon switcher at the bottom. Go back to the reading progress.

JASON: Oh, switcher icon.

BRAMUS: Switcher icon. Click on that one, and number four. That's the easiest one. Yeah, there's a few ways of approaching a scroll-driven animation and this is the easy one. And if you now click on the info icon, you should get like a little explanation of how is this thing built? Of course --

JASON: Whoa.

BRAMUS: You could check it out with DevTools, but this is like me writing down, this is how it works. I can walk through it. But maybe we should use DevTools to inspect it.

JASON: I mean, this is great. This is so cool to see. Just looking at this -- like this is how I expect an animation to work. We scale it on the X axis. So, left to right, down to zero. And when -- that's when you start. And then when you're done, it's scaled up to its normal size, which is full width. And this we stick it up to the top. And left, we make it 100% wide, give it a height of 1 REM. And look at this. This is beautiful. We just say "Grow," like use this animation. And we tell it to use the scroll instead of the regular timer. Like --


JASON: This is a brilliant solution because it doesn't feel like it changed what I know about CSS. It's something that I could have built that would have looped as like a growing bar. And then you just change out the timeline. And suddenly it's a completely different thing. And that's such a -- it feels good. Like you mentioned earlier that the original implementation was like JavaScript being kind of ported into CSS. This feels like CSS to me.

BRAMUS: Yeah, exactly. And it's as you mentioned. Like you start off with your existing CSS, your existing animation. If you have that one working and it runs over a certain time. The thing that you need to do is there's basically two things that you need to do. One is you remove the animation duration or you replace with the value of auto. Which you can see here in the animation shorthand. And then secondly, you add an animation timeline to it, and from there it will run on an animation timeline. But, of course, there's a few tweaks that you can do. Like which scroll timeline do you want? But by default, what the scroll function will do is it will look up the nearest scrolling parent of the element that you are targeting. So, from the progress element up, it will look at all the parent elements and the nearest one has a scroller that will be used to drive the scrolling. And in this case, it's just a document scrolling because the progress div is a direct child of the body, and the body is a child of the HTML. You have your root scroller, your document scroller.

JASON: Amazing. Like, yeah. This is -- it's just so good. This makes me so happy. And then so you implemented a few different versions of this.

BRAMUS: If you go to version 3, for example.

JASON: Okay.

BRAMUS: Yep. It's the same demo, it's the same output. But only the code is a little bit different. And what you see here is for the animation-timeline, we have passed two arguments in there. Block and nearest. And block is direction which you want to track. So, it's the block direction which is in our western world it's just from top to bottom.

JASON: Okay.

BRAMUS: If you want, you can also go in line in there so it goes horizontally.


BRAMUS: So, it's different axis so you're scrolling horizontally. But now we're scrolling vertically.

JASON: Fascinating.

BRAMUS: Horizontal and vertical, that's one of the four keywords you can use for that. And the last keyword is which scroller you want to track. And by default, it's gonna be the nearest parent. This is basically the default value here.

JASON: Okay.

BRAMUS: You can say root or self. And root will always map to the root scroller. If you have a scroller inside of a scroller, but you still want to scroll -- track the document, you pass in route.

JASON: Okay.

BRAMUS: And self is track myself. As I am scrolling, for example, if you want to change the background or something like that. I hope that was clear.

JASON: Yeah. Yeah, yeah. That is clear. That's -- okay. So, you want to -- do you want to keep looking at demos or do you want to walk me through building a few of these?

BRAMUS: Maybe we can take a look at the carousel step indicator and then one, and then we can build something, right?

JASON: Okay.

BRAMUS: So, here I have a carousel. But if you scroll through it horizontally, the progress bar will also move.

JASON: Okay.

BRAMUS: Like I just mentioned, you have the scroll function. So, in the arguments there, you would pass it inline because it tracks to inline. The inline axis of the scroller. But I did something else here as well. I gave the scroll timeline a name. So, that's what you can also do. So, you have this scroll function to say, hey, create me an anonymous scroll time instance. That's basically that. But if you want, you can be very explicit about it and say, hey, this scroller over here. I'm gonna give the scroll timeline name. Which is dash, dash, and then its name.

JASON: Okay.

BRAMUS: With the value of inline. And then you use that name as the animation timeline further down. Instead of the function, you pass in the name that you have given to the thing.

JASON: Got it. Okay. All right. I think -- I think I understand, and so, this is something different than what you would do, like... it's still scrolling. But it feels like kind of a unique use case here. All right. So, I'm gonna back out. What else would you like to like at?

BRAMUS: And then maybe one with -- let's take the image effects, the one in the center. That's like a classic one as well. So, and if you hit the little switch icon again at the bottom right, go to the number two there. Anonymous view timeline. Yep. This is also a scroll-driven animation. The image is revealing. As you scroll up, the image is revealing itself. But it uses a special type of scroll timeline. So, by default, a scroll timeline is just tracking a scroll as you scroll from the top to the bottom, you go from zero to 100%.

JASON: Okay.

BRAMUS: But this uses a view timeline which says track this element as it is entering, as it is crossing the scroll port. Which is like intersection observer if that rings a bell.

JASON: It is, yes. And this is huge because I love intersection observer with my whole heart and I hate -- hate! -- setting up intersection observers. Because I'm always doing it for something simple like this. So, this, replacing my entire intersection observer setup code, my life just improved in a very tangible way. This is amazing. I am so blown away by this. I actually didn't -- so, when Una showed me the site, we looked at it for a minute. I didn't realize I could look at the source code. I needed to come back and inspect this later, I didn't to want derail the show. I'm really excited this button is here where I can look at these and see. This is incredible. I did not know that Vue was an option. And that is gonna change a lot of how I think about what I can build on the web. Because I don't have to set up an intersection observer now. I can just run that and do a bunch of fun things as they scroll into view.

BRAMUS: Exactly.

JASON: Good stuff.

BRAMUS: It's so powerful because one line of CSS and it works.

JASON: Oh, man. This is what I'm talking about as improvements in the platform. As a developer, I don't want to write arcane code to make the things in my head a reality. When I was younger, I had a lot of ideas, oh, it would be cool if this was interactive like this, or this was hooked up to this interaction. I would talk myself out of it because as I looked into a it, the level of complexity to make that real, it was just too high. Too many cross-browser things to consider, it was written in JavaScript. I had to do my styles in JavaScript. Just broken stuff. This feels janky, I'm just not gonna do it. Good ideas died because I didn't have the bandwidth or the knowledge to build these very complicated work arounds. And now the browser is just giving us these tools that let us do this sort of thing in a way that doesn't require me to have like intense amounts of knowledge about how each of these things worked under the hood. I just know I want to do a thing, which is a CSS animation. I know to write those. I want to do this thing in the viewport. And add one little thing. I want this to play in response to the user scrolling up and down the page. I want it to just do that. It feels like a game changer to me.

BRAMUS: That's the beauty of CSS being a decorative language. You're not occupied with all the fine details and all the little knobs. You're just saying, hey, browser, please try and do this. It will do it for you. Amazing.

JASON: So, so good. Okay. Did you want to show any of these others?

BRAMUS: There's a bunch of them. I could talk on hours on all of these. But maybe dive into some code if you would like to do that.

JASON: Okay. Dive into the code. Should we use a CodePen? Should I stand up a local site? What do you think?

BRAMUS: Oh, whatever you want. Maybe CodePen is the easiest. Then people can check out later.

JASON: Okay. CodePen. So, I'm gonna set up a CodePen. And we're gonna say CSS scroll-driven animations with Bramus. Save that. And... I think I can -- I always forget how to share these. Here we go. This should let anybody who wants to kind of follow along live as we go. It does not make it collaborative. So, you'll fork it if you change it. But this will let us get started. And I'm just gonna drag that JavaScript right out of the way there. Because we're not gonna need it today, friends. All right. So, what would you like to start with? And I can give us some elements to start with.

BRAMUS: Maybe we should try and re-create an effect on the list where every list item fades in as it comes into view and fades out as it goes out of view. Because then I can talk to you about the animation ranges and whatnot.

JASON: Let's do that.

BRAMUS: Let's have a list.

JASON: I will set up a list. And our list is going to have -- we can set up like a little image. And maybe we won't start with an image. Maybe we start with like an H2. And we'll say a name. And then we'll have some kind of a description here. Maybe do some Lorem Ipsum copy pasta. But for now, just give some space. And then --

BRAMUS: Exactly. Let's copy-paste the thing.

JASON: Those. And then I and just very quickly do like a list style : none. Merge in of zero, padding of zero. And our list items we can -- we can be like... do you have a very specific way that you write your properties? Like I have to alphabetize or my brain short circuits.

BRAMUS: I try, it's for the first five minutes. But then it all goes out of control. It's like, hmm...

JASON: Just kind of like a very -- a very simple like rudimentary setup.

BRAMUS: Yeah, perfect. That's what we need.

JASON: And we'll just -- a little centering there. Okay.

BRAMUS: All right. So, what we basically want to do, we want to fade in these things as they enter the scroll port. That's the point that we want to do.

JASON: Okay. So, I can set up a frame, and I'll do opacity zero. To opacity 1. And that's how I would do this. And then if I were to just kind of set this up I would say like animation, fade, 1 second, linear. All of these to fade in like that. And then they're done. Nothing else happens.

BRAMUS: All right.

JASON: So, to hook this up on scroll...

BRAMUS: You remove the duration.

JASON: Okay.

BRAMUS: So, 1 second, throw it out. And then set animation-timeline to the value of view, which is the function. And now as you scroll... you will see that they fade in from the moment that they are -- it starts like when they are at the very bottom of the scroller. And then by the time they are at the very top, like when they have just exited the scroll port, there they are at opacity 10. That's what the view time does. It creates a range from just underneath to just above. But now we need an extra property. We want to shrink it down. No, fade in when you are at the bottom. And then you go just at the top. Like run to there. And for that, I have a little helper website. And it will guide you through it. So, if you open up scroll driven again, I have a little tool on there that will help you.

JASON: Okay.

BRAMUS: If you scroll down here on this page, yes. And then the view timeline ranges visualizer. The one on the right.

JASON: Okay.

BRAMUS: That's the one that you need.

JASON: That's handy.

BRAMUS: And if you click something, the click to start will go away. It doesn't scroll. You have to drag it. Zero to 100%. That is the default range.


BRAMUS: That is the full range.

JASON: Got it, okay.

BRAMUS: And these things have a name. So, you have several ranges. You can change it with the drop down button there at the top right that says "Cover." It you change it to contain, for example. And you can see -- and then the bottom one, set it to mirror. That's gonna be easiest.

JASON: Oh, mirrored, okay.

BRAMUS: Yep. This is the contained range. It runs from zero to 100%. When the item is sitting at the bottom edge until it goes to the top edge.

JASON: Got it.

BRAMUS: And also the other range, which is entry. If you check that one. And you can guess what that one does. It runs the animation from zero to 100% when it is entering scroll port. So, that's --

JASON: Got it.

BRAMUS: -- the range that we want to target. We don't want the full range of cover. We only want this entry range.

JASON: Got it.

BRAMUS: And of course you have exit which is like the one at the top.

JASON: Okay. So, then for me that means in here, I want...

BRAMUS: A new property animation.

JASON: Animation range. Do I just like?

BRAMUS: entry, and that's it.

JASON: Okay.

BRAMUS: And now every itself will have a view timeline. It will create a view timeline that tracks it. It will run the fade animation from the entry. It's from just below the scroll port to the view. And you can tweak the numbers if you want.

JASON: We will make this a little more obvious what's going on by inverting the colors here. I think that will help.


JASON: Because then you can kind of see them coming in.


JASON: Like that's cool. We want to do a little bit more to make it a bit more obvious when the colors aren't inverted like this. Because it's kind of -- it's very subtle right now. Which is -- I mean, sometimes that's actually like great. You want it to be just subtle enough that you can feel that something is happening. But it doesn't draw a lot of attention to itself.

BRAMUS: What I like to do here is that the from position. So, the starting position. I want to translate the thing a little bit down so that when it enters, it's like -- moves up a little bit.

JASON: Okay. And to do that, I translate why and you want to translate it down.

BRAMUS: Translate why won't work. That property doesn't exist. Yet. We're talking about it. But you want translate zero percent on the X axis and then, for example, 50% of to 20% on the Y axis. To push a little bit down.


BRAMUS: It goes up. One tip, by the way. We didn't repeat translate in the two keyframe. Because the default for translate is don't translate.

JASON: Right.

BRAMUS: And the same for the default value for opacity. It's one. We can just remove the two block there.

JASON: Oh, interesting.

BRAMUS: So, if you throw it away, it will still work.

JASON: Cool. I did not know that.

BRAMUS: So, that's the entry range. If you want, you can tweak the numbers. Because now the element needs to be fully in view. Maybe you don't want that. So, you can also tweak the numbers. So, you can -- instead of just entry, you can say, entry, space, zero percent. Space, entry, 50%, for example. Entry, 50%. And then the animation will run from when the element is just outside the scroll port up to the point where it's halfway in the scroll port.

JASON: Oh, okay.

BRAMUS: So, it runs a little bit faster. If you want to set it to 150%, for example, it also works. So, then it lags a little bit.

JASON: Oh, see, and that's great. Because now -- now it feels snappy and is like a little more visible what's going on.

BRAMUS: What I really like to do, by the way, is these percentages, they like depend on the size of the element itself. So, if you have a shorter element, it's gonna like -- the animations won't want to go over the same distance. So, what I like to do is I take entry 100% which is like entirely in view. But I wrap the 100% in a calc function.

JASON: Oh, I see!

BRAMUS: Calc 100%, plus 20 pixels, for example.

JASON: Got it, yeah.

BRAMUS: Or like zero percent minus 150 pixels. You can do calculations in there. It's really cool.

JASON: Because then if we take one of these... let's take probably one toward the bottom so that we can see the difference and make this a lot longer. Then... instead of feeling...

BRAMUS: Now it takes longer. What we can do is the calc one. Set it to zero percent minus 200 pixels, for example. Or maybe plus 200 pixels. Then it's always a fixed distance of 200 pixels that it will move.

JASON: Got it. Okay. So, in -- and then it's done, even though we're not in view -- oh, yeah. Okay.

BRAMUS: That goes over the same distance.

JASON: Great.


JASON: So, lots of ways that you can tweak this to make it suit your specific interaction goals.

BRAMUS: You can change the ranges, zero percent to 50%. That way it will animate from just under the scroll port to just under the scroll port. And you can calc -- it has so many options here.

JASON: Oh, yeah.

BRAMUS: The very center.

JASON: That's cool. I mean, this is great! And like, you know, this is one of those things that it just -- it's subtle. It feels good. It makes you want to kind of keep scrolling a little bit. And so, obviously, that means it needs to be used with a little bit of care. Because if everything on the side is doing this, it's gonna be real world and distracting. But used tastefully, this is such a nice power up to a website. It takes something like moving between your blog list and gives it a tiny bit of motion, right? And that tiny bit of motion can have a big impact, I think.

BRAMUS: This demo right here, we have it. We can do the fade in. If you want to do the fade out, it's really easy.

JASON: Okay. Let's do it.

BRAMUS: We can do that in like 5 minutes. So, when you set a value to a property to have multiple values, you can just come and separate them.

JASON: Right.

BRAMUS: So, for example, with animation, you can do fade linear, comma. And then fade out linear. And then with animation range, you can set a second value. So, maybe just for convenience, set it to entry, comma exit.

JASON: Okay.

BRAMUS: So, the one value needs to be. The first value is entry, and then the second one is exit. But of course if you can --

JASON: Oh, I gotcha.

BRAMUS: The long version. Yeah, entry, comma, exit.

JASON: Okay.

BRAMUS: And then we need to create the fade out keyframes, of course.

JASON: All right. So, copy this. And two, right?

BRAMUS: That's two. And then the translate needs to be to make the number negative. Exactly that's it. And it --

JASON: I screwed up because I didn't change the name.

BRAMUS: And I don't think it entirely works, it does because of the overlap. Sometimes you need to play a little bit with the film mode. What I do is the entry animation, I set that one to backwards. So, fade linear, and just backwards as a film mode. And then the end animation, the exit animation, I set that one to forwards.

JASON: Okay. And I don't -- so, I've seen that before. But I don't actually know what it does. What is the film mode in animation?

BRAMUS: The film mode in animation determines what should happen when the animation not running. What part of the keyframes do you want to show? The before part at zero percent or the 100% part, the forwards one, or do you want so set both? For example, if you're at the start, set the first frame, and if you're at the end, that settle both. That's forwards, backwards and both. And maybe a forward value, but I only use these three.

JASON: Okay. Cool. So, this, then, is basically what we're saying -- and the reason that you do this -- is that when you've got these two animations, if my view port was shorter, they might collide. We would still be animating in at the same time as it needed to start animating out. And by setting backwards and forwards, we bring them closer together so that they look smoother as they move through?

BRAMUS: You're basically doing the opposite. You're saying when they are at the outer edges, the entry one, that one goes backwards. It remains at opacity zero when it's way outside of the view.

JASON: Oh, okay.

BRAMUS: Yeah. And here it doesn't like really matter because the end frame of the fade one is the same as the starting one of the fade out one which is at opacity zero translates as zero.

JASON: Right, right.

BRAMUS: But if you have other types of animations, I like to do this one. The entry one to backwards and the exit one to forwards.

JASON: That makes sense. Backwards means it goes back to the from. And forwards means it goes forward to the two. That makes sense. Got to wrap my brain around this. Okay. Cool so, this is very cool. What -- what else should we show? Like should I... should I wrap things in -- in scroll dives and like make a pile of these? Or do we want to create separate pins? Or what do you think?

BRAMUS: Maybe create separate pins, yeah.

JASON: Okay. We can do that.

BRAMUS: Or maybe we should go into a little debug their I built. Because that one is really healthy.

JASON: Okay.

BRAMUS: Like in the ranges in the beginning, I was also very confused. When I read the spec and when we were refining the spec, I was like, what do these ranges mean? I don't understand. So, I helped -- the tool that I built already gives you a little hint at that. But I built an extension to DevTools that lets you debug it in DevTools itself.

JASON: Okay, I do...

BRAMUS: Back to the home page. At the top, there's a bunch of links.

JASON: Here?

BRAMUS: One is to see the demo, learn the syntax, which is an article. And then get the extension. Yep. And then you have a link to the scroll debugger extension.

JASON: Got it, okay.

BRAMUS: I'm not sure -- it should.

JASON: Yeah, I haven't had too much of a trouble with it. But I guess we'll find out. Yeah. And in chat, ayush was sharing this. You have got people.

BRAMUS: One note, the debugger doesn't work in iFrames. And everything in CodePen is an iFrame.

JASON: Okay.

BRAMUS: Open up your pen in debug mode and then you can inspect it.

JASON: To do that...

BRAMUS: That's a layout icon at the top. Yeah, that one. And then debug view. Then you have the standalone page.

JASON: Okay.

BRAMUS: And you can inspect on one, yep. So, you have -- you grab the -- yeah. And then at the top, you have this tab bar, styles, computed layout, eventlisteners, it had the arrow. There's a new one in there. That says scroll-driven animations. And now if you scroll the page, you can see what's happening. So, maybe grab like the fifth line on the page. That's gonna be interesting.

JASON: Okay.

BRAMUS: So, now you see what's happening. You see a visualization of the scroll port. And then you see a visualization of the tract box and actually --

JASON: Oh, that's cool...

BRAMUS: And the actual animations.

JASON: And then I can choose the animation.


JASON: That's very cool.

BRAMUS: Now what's also possible is if you hit the add values there at the bottom, the bottom right.

JASON: Here?

BRAMUS: Yep. Maybe make it a little bit bigger so that you can see it more clearly. Then it also draws some to and from boxes. For the ranges. So, these starting positions. And you can also change the values here at the bottom. But this is like straight into DevTools. And it will also sync back to the actual element on the page. So, if you change, for example, the percentages, exit zero percent, if you change that to 50%.

JASON: 50%.

BRAMUS: And then you need to blur it -- then the box gets updated and then the animation will also run at a different point.

JASON: And there it goes. So, the rest of them are still standard. And this one... this is getting real weird because we messed with it.

BRAMUS: It's for 0.0. If you find a bug, please file one.

JASON: I think I just gave it really bizarre settings. Let's see... zero...

BRAMUS: You need to blur the text field. Okay. You did that. Yeah.

JASON: Now it looks like I just broke it. It's playing the other one. Interesting. Still... a very, like --

BRAMUS: It broke.

JASON: What a handy tool to be able to see this stuff in action. Like this alone kind of pays -- pays for the price of admission there. Because for me, like a lot of times I know what I'm -- I know what I'm trying to do. And I know what the value should be. But I can't always visually map the number on the screen to the behavior that's actually happening. So, having something that can do this for us that just shows us, this is the animation you set. Here is where it fires. Oh. I want that to fire later so I can tweak the numbers to move it up or down or whatever it is to get what I want. Solid stuff that's really good.

BRAMUS: And top right, you can see the numbers. You can see the number going up from zero to one. Which is the full range. But also just limited to the effect. And then also the actual pixel offset value that you get there. Yeah.

JASON: Cool. This is great. So, this is like the actual element. How much of that view is happening. So, you can see it goes from zero when it's off to one. And then this one is the full page scroll. So, veer at the very top, one at the very bottom...

BRAMUS: It's the full range. So, when the item is sitting underneath the scroller and sitting on top of the scroller, that is the full range.

JASON: And then this here is the pixel offset. So, how far down we've scrolled, right?

BRAMUS: Yep. Exactly.

JASON: Very cool. I mean, these -- that is also -- this is great. This is like a really handy extension to have.

BRAMUS: That's why I built it. Because I also needed this for myself. I wanted -- I want to do stuff, but I don't know where the boxes are. Help me out. So, I built this to help me. And it can also help you. So, win-win.

JASON: Yeah, this is great. So, let's see... I have... where -- here we go. I'm just gonna drop a link. I already shared it. But if I share it, it goes into a channel in my Discord so that everybody can find it later. This is great. Like I -- I love -- I love what we're seeing here. We've got about 30 minutes left. And I've seen you do some stuff that absolutely melted my brain. That didn't look like a scroll-driven animation. Do we have time to put together a rough demo of something like that in the 30 minutes we have remaining?

BRAMUS: Yes. Let's go for it. Which demo are you talking about, I'm curious?

JASON: You did -- scroll-driven, this one was really, really cool. And then this one was very, very cool. This also is very cool. So, this one I imagine is probably a little more than -- I don't have the assets for this one. But something like this, or something like this... are both extremely cool. This might be the most like tractable in 30 minutes.

BRAMUS: Yeah I was gonna say, the cover card, we see that on many websites. And with CSS, we can mimic that and achieve exactly the same. This is a really good one.

JASON: The landscape and text one. You're talking about the cover card here? Let's do it. I'm going to create a new pen.


JASON: And scroll-driven animations with Bramus. Part 2. Okay. And then I'm gonna set up a -- should it be a separate element? Like if I'm -- if I was gonna mark this up, I would probably end up with like my -- my article element. And then I would have for that header, I would probably just use a header element. And then I would have a -- like a section for the article copy. Is that gonna be compatible with the way that you would build this? Or do you want to tweak that? No, this is good? Okay. So, I'll have an H1 and we'll call this great article. Okay. I'm gonna save this. And then I will share the link for everybody. If you want to follow along. And then inside I'm gonna go get some Lorem Ipsum.

BRAMUS: In CodePen, if you hit Ipsum and then load tab, it will generate a Lorem Ipsum for you. Or maybe Lorem tab?

JASON: Oh, look that the! That's handy. Okay.

BRAMUS: But it only gives you like one paragraph. So, yeah. Maybe is handier because it gives the HTML elements.

JASON: I thought it did. I thought this one gave you all of the markup. But it doesn't... whatever. Edit as HTML. And then I'm gonna go grab all of this. And drop it in here. Okay. Do a little format so that it doesn't hurt my eyeballs. And then -- good. All right. So, then the other piece that we need is an image of some sort. So, I'll just remember to unsplash. And I am gonna make this article about donuts. So, we'll just grab... a full screen donut image. And come back in here. And let's see... do you -- should I set it up as a -- like a background image on the header?

BRAMUS: Yeah, set it as a background on the header element.

JASON: Okay.

BRAMUS: So, that way you can do background cover. Like just to stretch it out a little bit.

JASON: Okay. And we'll do background, size. Cover. And then we'll set the height to be -- started at 100, right? Looks like I also need to reset the body here. And I think that might be my -- let's see. So, actually, why don't we just have this on a display flex. And then -- is there -- I feel like at some point I got shown a shortcut for align -- align items and justify content as like one property?

BRAMUS: Replace content.

JASON: Place content?

BRAMUS: Yeah. Center. Maybe try display grid? Or place content or place items? It's one of the --

JASON: Play grid, place content center. Gave us exactly what I wanted. And I am so happy. This is -- this is also magical. So, then let's see... so, we've got -- that's kind of all we need for the markup. We've got our header and our piece, I think. And then if I take my... I don't know. We can just do something like -- background size, background...

BRAMUS: What I also did is background position 50%. Or center. To make sure it's lined up.

JASON: There it is. There's our thing. Okay. So, then we have something like that. I'm gonna set the H1 to have just a little bit of background color so that... say, like, HSL... we'll go with -- zero. Separation is gonna be zero. We'll just make it black. Zero... and say 25? Yeah. K. Then we can make it width 100%. That didn't do what I wanted.

BRAMUS: There it is. W.

JASON: And padding, I don't know, 2rem.

BRAMUS: What chart with the W by the way, if you have a system with classic scroll bars. We have the overlay scroll bars that go on top. With the classic, they don't take the size into account. You can see that in Firefox. That's a bit of a pity.

JASON: There's. That's probably legible enough. And yeah. Let's roll from there.

BRAMUS: All right. You want me to walk you through it or you're gonna take a guess what you want to do?

JASON: So, I think -- yeah. I mean, what I would do from here is after making this breathe a little bit... and then the width of... 90%. So, what I think I would want is -- you know what? To be completely honest, I actually don't know. I don't know how I would do this.

BRAMUS: All right. I'll drop you some clues, right? Let's work on this together. Right now the header is 100vh in height. But at the very end, we only want it to be 10vh.

JASON: Okay.

BRAMUS: So, that should be part of our keyframes that you want to animate to a height of 10vh.

JASON: Okay. So, we want to go to height of 10, right?


JASON: And then if I set my animation, it will be header scroll linear. And animation timeline I'm guessing is gonna be "Scroll." So, then... oh, yep. That goes bad.

BRAMUS: Yeah. So, I run into this as well. So, the problem is that when you are calculating a scroll timeline, you are calculating against total scrolling distance that you have. But if you are now shrinking the header, your total scroll distance is also shrinking. So, all of a sudden it goes like, boop! And it's --

JASON: Oh! Yeah.

BRAMUS: So, the work around is we need to make sure that this header is sticky. But the problem with sticky -- so, my guess would be oh, just use position sticky on it. And then we'll do it. The problem with sticky is the thing never leaves the actual scroll port. So, my solution they use instead of "Sticky" is I make the header position fixed. So, it always stays in view and it's against the position view port.

JASON: Okay. Position fixed.

BRAMUS: Right.

JASON: For a second...

BRAMUS: Yes, so --

JASON: I can't tell if that like opted weird or if that was glitch. I'm gonna save it. I'm gonna reload it. Autosave is enabled, I'm gonna reload it, and I'm going to scroll. I can not scroll.

BRAMUS: The problem with position fix, you take it out of flow and you just drop it on top.

JASON: Oh, right.

BRAMUS: But all the text that was underneath has shifted up. So, you need to counteract that. And on the text, you need to say, well, your margin top is 100vh. Because the text is shifted up, you need to push it back down by 100vh.

JASON: Oh, okay. Okay.

BRAMUS: And now hopefully you should be able to scroll.

JASON: Okay. I can scroll. But I broke something... did I break something or is my Internet trying to like short circuit on me?

BRAMUS: I could still see and hear you.

JASON: Yeah. Okay. Hold on. I'm just gonna reload again and see if maybe...

BRAMUS: You could always right click and inspect it, right?

JASON: Yeah.

BRAMUS: Or maybe top zero to make sure that it's there somewhere.

JASON: Yeah... here is my header. It is missing.

BRAMUS: So, if you set it to top zero.

JASON: Okay. All right, all right, all right.

BRAMUS: maybe we should start off and just remove the animation, for example. To make sure that the header is there.

JASON: Okay. No. You should be gone now.

BRAMUS: Okay. Yeah.

JASON: Okay. So, the cover is there.

BRAMUS: All right. Now you've put back the animation. The view is reloading. And yes. It is scrolling. So, right now you see the header is actually shrinking from the full size to 10vh. But it's not really synced. And the problem is that by default, a scroll animation runs if you scroll from the very top of the scroller to the very bottom of the scroll. But we don't want that. We want like to shorten the range because the header should shrink a little bit faster. And that's --

JASON: Okay.

BRAMUS: -- where the animation range comes into play. Like with the entry timeline, we have the cover and whatnot. Far scroll timeline, we can just set it to some actual values. And for this one, first set the animation range to entry. To just 0vh space at 100vh.

JASON: Okay. And I just added more text to demonstrate the problem with this. Because with a shorter page, it's no problem. It just doesn't scroll at the right height. But with a longer page, look at this, it's just broken. Like my text is disappearing under the header. So, this is -- this is the sort of thing that we like -- we have to fix this. So, you said animation timeline, I need to set the animation range.

BRAMUS: Animation range, yep.

JASON: And you said?

BRAMUS: Zero vh, space, 100vh. That way you're saying, like, hey, header, when you're scrolling the page for 100vh, shrink to your 10%. Yeah. This is a very good example. You have done that. Now it switches to this. There is because of the film mode. So, we need to set the film mode to forward so that when the animation is done, it keeps that very last frame.

JASON: Makes sense. Okay. Oh, wait. Did it actually reload? Is it four words with an S? Or forward?

BRAMUS: Forward. Yep.

JASON: There it is. Oh, my goodness.

BRAMUS: Okay. Oh!

JASON: What is happening?

BRAMUS: It was there. It wasn't there.

JASON: It dumped my change. I think either my connection or CodePen is having a moment. Because I'm -- it's like not loading as fast as I'm used to. Okay. So, that's doing what I want.

BRAMUS: But you can see it's not perfect. Right?

JASON: Yeah.

BRAMUS: Right. So, I've set like -- this was my first idea as well. I want to animate a header. If you go from zero to 100vh. But actually, we need to subtract the remaining height. So, we want to animate it not from zero to 100vh, but from zero to 90vh. So, the remainder -- the remainder of the finishing height. And if you set it to 90vh, it should work. Like the text now always stays -- yep.

JASON: Yeah...

BRAMUS: You could give it a little padding. The little div to not have it stick to the header. But this is a demo. There you have it.

JASON: That's fantastic. And then if we wanted to make this more like legible, we would probably go with something -- something like that. And look -- look at our -- like... this is is the sort of thing that we used to spend hours in tutorials trying to get right.


JASON: And to make it not feel weird and not bounce our text around. As somebody who is attempting to build good experiences like this, I -- there were like think pieces all back when Medium was like the way that we talked about web Dev for a while there. There were all these great think pieces because why you should never do this because it introduced jank and weirdness and all these problems. And now here it is, non-janky, progressively enhanced.

BRAMUS: There's little notes to make with this one. This one is gonna be janky because we are animating the height. And animating the height doesn't work on the compositor. You have to transfer opacity, those run on the compositor. Width, height, background color don't. Thankfully, though, we have very clever engineers on our time. I think about two months ago, they said, we should fix that. They are working to make this work in the future so you as an author don't have to think about, does this run on the compositor or not? We are going to tackle the main cases. If you want to animate a background color, for example. That should run the compositor. And width and height, that should run on the compositor because we often do that.

JASON: Right. I mean, this is fantastic. And some good notes in the chat about like making sure that we're respecting preferred reduce motion. Here is maybe a question. Because not every -- like prefers reduced motion is not prefers no motion. We're just trying not to trigger vestibular disorders and stuff. Right? So, when -- where do you draw the line? Like for me in my head, the things that I immediately think about are like no strobing, nothing like whooshing around the screen. But something like this -- is this -- is this something that you could keep as reduced motion? Or like where would you -- where would you draw the line?

BRAMUS: Of course, as with everything on the Internet, it depends is the answer.

JASON: Sure.

BRAMUS: But with this, I am perfectly fine with this. Because there is still this direct link between you moving the page and the thing shrinking. So, it's like a one-on-one type of thing right here. Whereas if you go to scroll reduce animations, the cards that fade in and use a view timeline. Like at the home page -- yeah. Like these little cards here at the bottom. Like this is a bit weird, right? Because there's some clipping going on there. And there's a little translation going on there as well. And people will get nauseous of this because it's like a lot of movement going on. So, this here on the home page, I wouldn't do that. Prefers reduced motion on. The shrinking header, I think, I think that's fine. Of course, there will be people that say, I'm getting nauseous off this. But I think that's one of the safer ones. Yeah.

JASON: And I guess the nice thing about something like this is that you can control it. Like if you need to go slower on this, you have the control for how fast it goes.


JASON: Which is kind of a nice bonus as scroll driven animations go.

BRAMUS: And that's why this is scroll-driven animations. Because there is a direct link between you scrolling and the animations going backwards and forwards. This is not scroll-triggered animations.

JASON: Right.

BRAMUS: Scroll-triggered animations, you are scrolling and at the certain scroll set, the animation will run on the document timeline, its own time. And you lose control as the user. Because if you stop scrolling, the animation is gonna run.

JASON: Right. Yeah. I mean, this is some extremely cool stuff. So, we probably -- I mean, actually we might have time to do one more demo if you want to.

BRAMUS: You said 30 minutes and we did it in 10.

JASON: Yeah. So, we've got --

BRAMUS: That's the cool thing about this API. It's really easy. If you know animations --


BRAMUS: The duration, add an animation timeline to it and you know how to do it.

JASON: So, I would like -- if you are okay with doing one more. I want to know how you got a scrolling session to move the opposite direction. So, I'm gonna -- I'm gonna pop open one more pen.

BRAMUS: For this one we might need half an hour. But we'll see how far we get.

JASON: Oh, really.

BRAMUS: No worries.

JASON: If we can't get there, we'll just go look at the demo. With Bramus, part 3. Save. I'll grab the link. Maybe I'll grab the link. Icon. Here we go. Link. Shared. Here we go. And I'm going to create we'll say a main and inside of this main, I'm gonna have three sections. Put up one of them to start. Let's see... do I still have... that image on here. So, I'm just gonna probably run the same image to say us from having to go hunt for them. If we get way ahead of ourselves and are done faster, we can get more.

BRAMUS: I like that you're putting up an alt in there.

JASON: I -- I've just made it a habit. Like I don't create image tags without alts. Because if I don't do it now, I will forget.

BRAMUS: One tip with that, also set width and height attributes. Because browsers use it to pre-reserve some space for the image while it's still loading so you don't get like a layout shift. But for this demo, it's fine. You don't need to change it.

JASON: Actually, it's a good point. These are also huge images. Why don't I change this over to be like 600 -- this is the imgix API. So, we can just set it to a nice resolution. And then we'll go width of 600... and height of say 400. And now we've got nice, accessible images that are not gonna have weird jank when they load.


JASON: So, I've got... one, two, three of these. I'm gonna set up main to have a display of grid. We'll do grid --


JASON: Template columns. And repeat three 1fr. I'll set the section is kind of fine. But we'll probably need that in a minute. So, we'll set the image to have a width of -- we'll go 2x density. One of those. And then we'll set the aspect ratio to be -- what is that? Three...

BRAMUS: You can just type in the numbers. Or you can also do height also. And then it should automatically adjust the height based on the width and height attributes.

JASON: Okay. So, we got those. That should get them all to sit nicely together. I am happy. So, then we've got some scrolling to do here. And then I guess we can just set like maybe -- oh, no. We don't need that. The sections we would want to be like display flex maybe with a gap of 1rem and a flex direction of column. And that way they'll kind of look like a nice scrolling bit. A little bit more spaced out so we got a bit more to scroll. And now, please, I would like to see how to -- how to get this to work.

BRAMUS: All right. So, the trick that I did -- this is based on a demo from code drops. They built it with JavaScript. And it was like, this looks like something that scroll-driven animation can do so I went for it. The trick is the center -- all three columns start at the top and bleed out the page to the very bottom. The trick is that you want to take like the first and the third column and shift these 100% up so that they sit like at the bottom edge of the -- of the columns or what's the name? Of the main element. So, first thing that I did is on the columns almost, like on the main element that you have there...

JASON: Okay.

BRAMUS: I set overflow Y to hidden. Because we are gonna shift something up and they should be hidden by default. Yeah.

JASON: Okay. So, then --

BRAMUS: And then -- uh-huh.

JASON: Do an Nth child of one. And Nth child -- you probably just set this to be like odd or something. But instead, we'll do it like this. And you wanted to translate as nothing to the left and right. And minus 100?

BRAMUS: Yeah. So, if you minus 100, they are moved out. But the problem is that now they are moved by is00%. So, they are like way out of the screen. So, you need to calculate a little bit and you need to say, calc minus 100%, but plus 100vh. Because you want your bottom port -- your bottom port to sit at the end edge of the scroller. So, right now --

JASON: Okay.

BRAMUS: In the good starting positions, right? So, the middle column is still at its position. And the first and the third one are sitting at the bottom edge. That's like the start thing that we want to have. While you're at it, by the way, also the column, the flex direction of column reverse on to those alt children. Because you want their images to also be flipped. Right now we have the same images so it doesn't really matter. But yeah. So, it's column-reverse that you need.

JASON: Oh, column-reverse.

BRAMUS: And then the first item will be like the last one.

JASON: Okay. Got it. Okay.

BRAMUS: That's the basic setup. We have moved them on to their right positions. Now we need to animate them. On these odd children, you are going to set animation and link it up to some keyframes.

JASON: Okay. So, we'll do one of these. I'm gonna set the animation to scroller, Lin year. And then animation timeline --

BRAMUS: Just scroll because we're taking the scroller. Yep.

JASON: Okay. And I want this to just go to --

BRAMUS: Yeah. And now we need to transform the elements again. So, as we are scrolling down the page, the elements also need to move. You could think about this like for half an hour and not find it. What I always do there is I'll make a little drawing and I like draw it out on a piece of paper. And the final translate value that I need to get is calc 100% minus 100vh. So, we're basically inverting both of those numbers that we previously had.

JASON: Okay. And I have missed a step. What is my step?

BRAMUS: Keyframes, animation linear... yes, animation timeline... yes.

JASON: Translate, translate, translate.

BRAMUS: Let me check what I had here. And then my columns...

JASON: Animation scroller linear. Animation timeline. I don't need to mess with the range, right? Like the...

BRAMUS: No. Because you want to scroll from the very top of the page to the very bottom. So, if -- oh, maybe on the columns, set... I'm checking what I have here. I was gonna say position relative, but that one -- if I toggle it on or off in my code, it doesn't make a difference.

JASON: Okay. So, something I'm doing... let's see... anybody spot the typo? So, translate...

BRAMUS: A trans-- oh, no. It's written correctly a translate -- no. The direction is correct. I was gonna say X and Y are flipped. But that's not it.

JASON: Column reverse... okay. So, that means I am... what if I just make this... let's try just turning this off and we'll...


JASON: Maybe my --

BRAMUS: So, now you see --

JASON: That's it. It's doing the thing. Okay. So, that should be... that should be working. And for some reason, it's not. Did I capture it in this of my grid or something? In a way that would cause it to break with the overflow hidden or anything?

BRAMUS: I am trying some things out here locally. Hm. Reverse translate, animation scroll, linear. Yeah. That all looks good. Does the animation short hand only allow more values is the question? It allows more values. But not the timeline. That's why we need to do it apart. But if you removed the overflow Y on the main. Just to test something out. So, now --

JASON: There it is.

BRAMUS: It's doing stuff. And is it okay?

JASON: It's mostly okay. It's a little janky. So, it would need some tweaking for sure. But we are getting the effect which is pretty dang cool.

BRAMUS: Yeah. So, the problem with overflow Y hidden. Now I'm starting to doubt why my demo works because it has it in there. Is that you create a scroller that's just not scrollable. So, if you -- ah! I know. I know. So, the problem with overflow Y is that you create a scroller that is not scrollable. If you use the scroll function, it will find the nearest scroller. So, it will find -- the sections will find the main element which has overflow Y set to hidden. And use that as its scroller. So, if you put back the overflow Y on the main, that's step one. Now the scroll element will find that element as a scroller. But we don't want it. We want to track the root scroller. So, in scroll, set it to root. And now you have it.

JASON: And now we get it. Look at it go.

BRAMUS: Default, it will find the nearest scroller and we want the root scroller.

JASON: Beautiful.

BRAMUS: The demo there.

JASON: And right in the nick of time because we just ran out of it. Bramus, this was amazing. So much fun. I'm blown away by how much this open up for us. This is a very, very powerful API with so many cool things. My brain is overflowing with stuff we can build here. So, if folks want to see more, we've shared the scroll-driven animation site. Is there anywhere else you want people to go to dig deeper?

BRAMUS: On my blog I have a few extra articles that paint outside of the lines what scroll-driven animations can do. Scroll down, for example, you can see my previous post. You can use scroll-driven animations to detect a scroll or not. Which is a convenient -- unstandardized use of scroll-driven animations. But you can do it. And if you scroll even more down, you can use scroll-driven animations to mimic a snapped selector. So, down, down, down. Where is it? Yeah, here.


BRAMUS: You can use scroll-driven animations to apply styling to an element that was snapped. I think that's pretty crazy. As well as like an un-convenient use -- normal use -- not normal use -- of this API. Speaking of special uses of this API,, run by -- so, it's k-i-z-u.


BRAMUS: Yeah. And then Roman Komarov has their fit to width text that also has scroll-driven animation. He has a piece of text that adjusts itself to the available size. That's done using a scroll-driven animation.

JASON: Oh! That's super-cool.

BRAMUS: I would recommend people to check out all the articles that Roman has written.Er in so good. It's amazing stuff.

JASON: Very cool, with that, we are out of time, one more shoutout to Amanda and White Coat Captioning to doing the closed captions today, Netlify and Vets Who Code for making this accessible. And we are going to do backend stuff. You want to learn to build an API, with rate limits. James Perkins is going to talk about that. And using React 3 fiber, I don't know how it works. It's gonna be wild. That one's at a special time because Michael is in Australia and I didn't want him to get up at 3:00 in the morning. Rich Harris is coming back. We are going to look at Svelte 5 and ruins. And Andrew, email and JSX. Excited about that. Mark your calendar, join the Discord, get on the email newsletter, whatever the right thing is for you so that you can follow along and make sure you don't miss any of these. I'm going find somebody to raid. Thank you for hanging out we will see you next time.

Closed captioning and more are made possible by our sponsors: