 Hi there, my friend and friends. Have you ever wanted to make animations like this that are all scroll based? So it comes in and out as you're scrolling, maybe have images fade in as the user's going down, even have scroll linked animations for things that are going horizontally on the screen and maybe a couple of other things as well, all without having to write one line of JavaScript or rely on any third party plugins? Well, all of that is possible and it's exactly what we're gonna be covering in this video. And so to really understand how scroll listeners work and the different things we can do with them and how we can do all that, we're sort of gonna start off simple and slowly level up our game to really understand all the different things that you can do with them. And the very first one here that I didn't actually have in that first one is going to be one of those scroll watchers just because it's like the most basic, simple way to show or highlight how the scroll listeners work. So with this scroll watcher, you can see I've created the lime green bar that's across my head or all the way at the top there. And it's just basically position fixed height of 10 pixels. So we have something there with a background color and a big Z index on it. And what we're going to do is create an animation. So let's do an animation of scroll watcher because that makes sense, I guess. I mean, to say two is scale of one, one. And scale is its own property now, which is great. And one, one just means on the X and Y axis that our scale is gonna be like that. And that means here I actually want the scale to start at zero, one. And let's start it actually at 8.5 just so you can see it's shrinking it like left and right but it's keeping the height of it. So I'm gonna start that off at a zero, one. And then all we have to do, and this is like the easiest thing in the world, animation will be our scroll watcher, right? That makes sense. And I'm gonna put linear here just because if you use a timing function that's not linear, especially for a scroll watcher, it's gonna like speed up as you're scrolling which is kind of weird. But let's do our scroll watcher linear. And then what we can do is our animation timeline of scroll. And whoops, that's a function. So there we go, scroll and hit save. And just like that, it's not working because I said animation and not keyframes. Ah, there we go. Now just like that, the magic happens. That was a bit of a let down, right? When you think something's gonna work and it doesn't. There we go. Perfect. I hope people were like, oh, it's a new at animation. This is cool. I do apologize for that. So it's working, but of course it's growing from the middle which I think is kind of weird for one of these things. So here I can just do a transform origin of left. And the transform origin still works even though I'm using the individual scale property. And with that now you can see it's growing left to right. There's a few different things that you can pass into here but for now we'll keep it simple and we're gonna sort of step up our game as we go on. But one of the things you can actually do is tell it which direction you're looking for. So if I put Y here, it will continue working. You can see it's still coming in. I could switch this to X and now it's not working because it's looking for scrolling left and right. So let's actually just come here and say body. Width is going to be 200 viewport width just so we get a scroll bar going that way. And now you can see it's actually like tracking my scrolling left to right instead because I told it that it should be looking at scrolling in the X axis direction. If I leave that blank it will default to the up and down. And instead of X and Y you can also put a block. Will block is your up and down and I can say inline and that will be my left to right watcher right there. So a few different things that you can pass in. A little bit of a weird example there. So let's get rid of that and keep on going. Basically it's looking, it's gonna start the animation when you're zero keyframes is when the scroll is all the way at the top and a hundred point of the animation is when the scrolling has reached the end and there's nothing left to scroll. So that's how this is working. It's nice and easy and it works like amazingly well which is really cool. And it's just like the simplicity of that just makes me so happy. But we wanna do more complicated things, right? Let's fade in our images, getting these things to follow our scroll position and some other stuff. So let's get into that and for this I'm actually going to comment this out because I find scroll watchers really annoying and I'm scrolling around. And so for this next part, what we're gonna do is I'm gonna skip this part now. We're gonna look at the fading of the images because that's sort of the next stage along the way here in what we can do. And you can see I have my article images selected right here. I'm doing a silly YouTube demo. So like I just have images thrown directly in my article and I'm like using on splash for them and stuff. So if you wanna class on these or whatever it is that works better for your use case obviously come in with the selector that you need for these. And for now actually, let's come in with the animation and I'm gonna do a keyframes and not animation keyframes and we'll call it fade in. And I'm just gonna say from and you can just put 0% here if you want. That's just the from is your 0% keyframe. Let's say a scale of like 0.8. So they start a bit smaller and they're gonna grow a bit and then we'll do an opacity of zero. So they don't exist yet. And then we're gonna say to a scale of one and an opacity of one. And then as you guessed, we come here and we say the animation which is our fade in. And once again, I'll go with linear but where things are a little bit different is the animation timeline. If we use scroll here, like I mentioned, it's looking at scrolling, starting the animation when we're at the very top and ending the animation when we're at the very bottom. So like the images don't really, that doesn't work. And traditionally we would have needed an intersection observer with some JavaScript, right? To be able to get this to work. So we're only looking at it when it's inside of the viewport. Now all I have to do is this and watch this. This is so cool. The animation will start when it enters the viewport and it will finish when it exits the viewport. So it's keeping track of when it's visible. Now that has its definite limitations because ideally my animation, I'd actually want it ending probably about here and maybe even starting a little bit later. I don't want it starting here. I want it to sort of start maybe here. Luckily, that's not actually that hard to do and there's a few different ways we can do it. And I'm gonna start with the one I find super onintuitive and then I'll show you another option that we do have. But here inside this view function, I can actually specify the offsets from the top and the bottom for where this is gonna be happening. So I can say here, let's say 100 pixels. And I'll start with that or let's do 200 or 250 because it might be a bit more obvious. And what that means is you can see the animation is, and I did this on purpose to have the from here instead of having it on my image just because we're really gonna see when the animation kicks off and I'll move myself up. So you can see the animation's only starting right there because my image exists, there's nothing being applied to it and then we're setting the opacity to zero when the animation starts. So we see it kicks in once it's 250 pixels into the viewport and then as I'm scrolling this way, it's actually gonna finish when we're about 250 pixels away from the top or when we are, you know, this part here will be at an offset of 250 pixels from the top right there. And you can see the next one is clicking in and doing the same thing. The reason I said this is kind of unintuitive is because you can actually pass two different values into this. And for me, they're backwards and they make sense. They're your top offset and your bottom. So it makes sense that the first one is your top and the second one is your bottom just because of how we think, but it actually feels upside down when it works because what we're gonna do, let's keep this one at, or you know, let's make this one 100 pixels and make this one 500 pixels. And the reason I'm saying it's upside down is because what this means is it's actually going to start when we're 500 pixels away from the bottom. And the animation is gonna end when we're 100 pixels away from the top. So right around here, we're getting to where the animation is finished. And to me, my brain just works that this should be where it's starting and this is where it should be ending. But this is my top offset. So this is how far away from the top are we when the animation will be finished. And this one is how far away from the bottom are we when the animation, so we're only watching it when it's between that bottom part and that top part. And I understand the logic behind it, but it just, it breaks my brain a little bit to think of it that way. So it's a little bit like mucked up, I don't know. But luckily there's other ways that we can control this that are a little bit more intuitive. And so to get to the more intuitive way of actually doing this, I'm gonna remove this from here and we're gonna bring in a new property which is animation range. And animation range is actually a shorthand for animation range start and animation range end. And this actually for me makes a lot more sense. So we're gonna say we're gonna start at 500 pixels and we're gonna end at 700 pixels. And what that means is the animation will start once it's 700 pixels in. So that's why we can see it, the animation starting when it disappears. So we're 500 pixels away from the bottom we're starting and then it's going to finish at the offset of 700. So in this case, we're always working from the bottom. And for me, that makes my life, I just, I understand that better, I guess. It clicks in for me a little bit more. So 500 pixels and then we're good to go. Now there's other ways that we can actually control this a little bit better as well. So instead of like, maybe you want it to start, like right now it's basically starting when my image is like 100% into the viewport. You don't wanna have, if you have different heights of images and stuff, you don't wanna have to figure that out. So I can actually use either cover or contain our two keywords that we have. So if I go with cover, it's gonna be sort of as soon as it's entering the viewport, it's gonna kick in and then we're finished once it's 700 pixels away from the bottom, or I can say contain and contain is the one where the entire element has to be contained on the viewport before the animation starts. And then you can see it's coming in and working. And then this is how far away until it ends. Or I can also use contain here. It's gonna start as soon as the entire thing is contained and then it's gonna finish right here when we're hitting the top of the viewport because the entire thing is contained and we're about to leave out the top. So it's kind of cool. We get like a few different controls here that I like cover. I don't cover seems to be a lot like the default from what I've been playing around with. Contain I actually think is kind of useful cause we're waiting for it to all be contained in there. And if I'm doing something like this, I can just come down and say contain like this instead with the shorthand and it's gonna work exactly the same. So I'm starting there, it's ending here and I can even then add offsets to the contain, right? So I could say contain and then 100 pixels. And what that means is it's gonna have the entire image will have to be in and contained and have an offset of 100 pixels before it starts. And then it will come in and go all the way to there. And I just find that's pretty cool that we can do that. But of course now this doesn't make much sense to have here cause it's obviously causing that weird flash and other stuff. I just wanted to use it cause it shows really well when the animation is starting. But ideally you would take that off from there and you would just include that on your image normally. So that way where the entire image is contained were a hundred pixels from the bottom and then it fades in and even that, I find this is actually probably not the best. So just cause we're getting all the way up to there. So let's actually just do this as like a 250 pixels and maybe a 500 pixels or something like that. So we just have a short range where this animation is happening. But this does open up another problem is when we get to the end of the animation and now that I moved this up to here, when the animation finishes, it's an animation is finished. It always goes back to the default state which we've reached. So here I just need to add a forwards. So when we get to the end of the animation it will stay at that last key frame. Very important that we do that. So we scroll in, we get to the end and then we stay there. And we get this fun little animation coming in for our images. Now one thing with this that I would caution with though is that in general, you wanna be really careful with animations that deal with scroll. This one may be a little bit less so though it is a little bit kind of much but especially with this one that we're gonna get to. So what I would really recommend doing is an app media and do a prefers reduced motion of no preference here. Which means that if somebody hasn't set any preferences in their operating system to reduce motion and they could have vestibular issues and other things where they get motion sickness from excessive motion on websites which can include things like we looked at and especially these types of things where we're gonna have reverse horizontal movements going. So like horizontal animations while the page is going up and down especially can be really problematic for people that have vestibular issues. So it's not that hard to do. We wrap that in this no preference media query. Most people are going to get the animation kicking in and sliding up but anybody who has set things up and if you open up your dev tools in Chrome anyway it is easy enough. We can just come into the command palette with a control shift P or command shift P on Mac and just do emulate reduced motion. There it is emulate CSS prefers reduced motion. I'm gonna turn that on and now with that on I might have to refresh my page. I'm not sure if you need to bother with that or not but now you have to see it just gives you the normal experience with no animations going on and they just get a regular website because if somebody's coming to your website and they're feeling nauseous they're leaving. They're not gonna like try and like force their way through it, right? So most people will still get the cool effect and people that have opted not to get it will not get it win-win for everybody. Now let's move on down to this next one that's down here and I closed my dev tools so the emulation is not running right now but let's go down to this one that's right here because this one opens up some interesting things that we might wanna do and just really fast actually before we move on to the next one I do wanna just mention that here we do have other options. I talked about cover and contain. We also have entry, entry is going to work so the animation is going to start as soon as it starts entering the viewport and it will be finished as soon as it's finished entering the viewport so the animation is done here. So you can see it's really linked to coming up to there. The other one is exit so it's the opposite. It's dealing with when the item is exiting the page so as soon as it starts exiting the page the animation will start and then it's finished as soon as the exit is finished. So you do have those options. You also have the entry, entry crossing is another one that we have where as far as I can tell it's very similar to entry and we have an exit crossing here as well, exit crossing and like I said, there's the cover contain and there is the normal, normal is the default but I'm sure there's actually a difference so the normal will start there and finish when we get to here and then we have the cover which as far as I can tell works very similar if not the same as the normal one. I think the most useful ones honestly are entry just because it deals with the entry of it and again you could put an offset here so I could say entry 100 pixels so we're actually going to delay it by 100 pixels and then it's going to start or maybe just to exaggerate, let's say 500 pixels so we have to be 500 pixels away and then it's going to start the problem here is it's going to go really fast because it's going to finish when we get to like as soon as the entire thing is in there but if you have a small little delay here it could be something that's worth it or you just set two different ones. You can set percentages and other things here it doesn't have to be in pixels I've just been using them up until now. There we go, some fun ones there but let's move on down to this section here we're going to deal with a different direction and for this actually I already have some CSS set up because this is from another demo that I did and let's just turn this on for a second and for this one I actually have some CSS already set up because this is from another video I did where I was just having these types of things that you sometimes see from time to time and I wanted to set it up and get it working so you can see they're just going to slowly scroll in one direction or the other but I don't want to do it over time I want to use the scroll timeline to be able to do it but before we do that I am going to come up and we're going to change this overflow X to be a scroll just so we can experiment a little bit with this type of scrolling instead because we can also do that with our view so I'm going to turn off this one for the moment and we're going to come on with this BG shifter which is going to make the background change and it's nothing too fancy I just want to sort of highlight and show you how it's going to work where we can come here and just say animation timeline and you might think I'm going to do view because we're sort of sticking with the view here but we're going to do scroll instead and the reason we're going to do scroll is because I sort of mentioned this a little bit earlier but the scroll is a little bit different because it can change depending on the context of where the scrolling is happening and so just to show you right now you'd think it would work because I set my scroll but if you remember before when we looked at this when I set it up, the default was looking at if we're scrolling up and down so what I actually want to do here is change this to my inline axis and as soon as I change that to be looking at the inline axis and I hit save you see the colors have come on and the colors are going back and forth and this one is blue and it's the opposite because I have the data direction on there and it's doing an animation direction of reverse. So now you can see, look at that, it's working and interestingly this is scroll and not view and the reason I'm using scroll and not view is because when we use this scroll function here it's looking at the nearest ancestor that has the scrolling on it so now it's not looking at my viewport scrolling anymore because this has a scroll bar on it it's going to look at the scrolling that's happening here and as soon as I have, because if I come back up to here even if I took this off, it's the same thing because I have an overflow hidden on this so once I do an overflow hidden we've taken the scrolling context for these elements away from the viewport and we've linked them directly to just these elements that are right here so that's even though this is hidden and that means I can't scroll this way but this scroll inline is going to work here and it's going to be looking at those these things and that means if I do want these to have an animation on them based on the scroll of the page if I try doing this, it's not going to work, right? So if I hit save on that, you can see nothing is working because it's looking at the context within its own element but there is no scrolling happening within that element so that's where I can actually fix this by saying don't look at the scrolling within that element, look at the scrolling and the root instead and now you can see as I'm scrolling the whole page the colors are actually shifting around it's not doing a huge shift but you can definitely see that there is a difference coming in as I move that up and down so anytime you're changing the scroll context of something which as soon as you change your overflows that's going to happen and that includes having an overflow of hidden if you want a different alternative that won't actually cause that limitation you can use an overflow of clip not going to talk too much about that one in this one, if you want to learn more about it I covered it recently in another video there should be a card popping up for that one we're going to leave that as hidden for now and what I'm going to do is leave this scroll set to root but here instead of using this weird background shifting color thing which is kind of weird let's go and change this back to my scrolling right here scrolling and now as I scroll up and down the page you can see that it's actually animating those as I go up and down I need a little bit of work I obviously broke things when I set this up because there's a bit of a blank area that's coming in there and there we go I fixed it I just wasn't I had some JavaScript set up that was appending some children and it wasn't working properly so we have enough children appended now that it's going and we have everything running the way we want it to and it has this going on now again these you want to be careful with they're kind of annoying when you're running with things like this so please do this with caution and ideally you'd be locking all of that scrolling behavior inside the media query with the prefers reduced motion like we've already looked at because especially this type of scrolling behavior really can be problematic and now the last thing that I want to look at for this one is doing that fun animation that we had here at the top where we scroll down and we have a few different things coming on just because it sort of takes everything we've learned and I think wraps it up in a nice bow and so I already have some styles set up right here for this area and just to get everything I'm stacking everything using grid I have the position absolute for my image in the background which is just make it easier to control instead of using a background image because it's its own element that I can do stuff on and the first thing usually with these types of things is we're going down the text can fade out so let's do that I'm going to come here with an at key frames fade out and that just means two opacity of zero nice and simple and then we can come up here on the article title animation fade out linear so nothing different there and again if you do want to experiment with the timing functions on these you can I just find linear is the one that has worked best for me and everything I've done but I'm sure some clever people come up with better use cases than what I've been doing up until now but that works and then we want to come here once again with our animation timeline and ideally in this one in general scroll you want to use if it really does need to be something that works for the entire viewport the reason I did use the scroll for this and not just view is I guess we could have done it so it's only when it's entering the viewport and only when it's exiting that would probably work okay I just wanted to make sure that the animation was basically always running and I wouldn't run into a part where it wasn't but it also showed us how we could target the route if we need to but here what we want to do is do the view so let's hit save on that except I did that on the header I don't want it on the entire header I want it on my header content and let's paste it in there so as we scroll down we want it to go away but ideally it's not going to start right away right we need it to only start when this is getting a little bit closer to being on the bottom so how do we fix that we have our animation animation range and in this case I'm going to go with exit so it's only going to start as soon as we start exiting the viewport except the problem with that is I mean you notice it I guess when we're really close to the edge here right so it's like but it's not as obvious as it could be so let's say exit and I'm going to say negative 200 pixels and the reason for that is I want it to have an offset of 200 pixels so as I'm scrolling down I want it to start the animation here 200 pixels before it starts to exit and that looks a lot better so it's a little bit more obvious that the text is fading out and so and it's completely gone by the time we get out of the viewport perfect for what I want to do here so I'm super happy with that and if ever you're having trouble with this let's say you had a grid set up and maybe the element is bigger than you thought it would be one thing that can be useful is to put a border on something yellow or an outline solid and the reason is just so like you know this is where you're going okay I'm 200 pixels away from here and that's when it's starting but sometimes if you're dealing with like the bottom offsets and things like that just like this is sometimes a lot bigger than you're expecting or there's some extra padding or something so it's mucking up when you think your animations will happen so definitely throwing borders on things quickly can definitely help at times so that one looks pretty good and now we can move on to the image which I've already set up here and for this one we can try and do a couple of different things right so my animation my opacity is currently at 0.5 but ideally I want to make the image actually become more opaque as the people scroll down so it's like you see it a little bit more before it finally fades away so let's come in with an at key keyframes and let's just call it I guess like header header image animation because I don't have a better name and we're gonna do some weird stuff here so I wouldn't like a fade out you could use anywhere this one you probably wouldn't want to use anywhere so let's say at 25% of the way through the animation we actually want the opacity to be back at one and then we could say at maybe 85% of the way through the opacity gets to 0 this is going to work but be slightly problematic when we use it but we'll see what that is in a second so once again we do our animation of my header image animation and linear and then we can do our animation timeline is going to be my view and we probably will muck around with the range as well but so it's gonna start and it's fading away and there we go it's gone and then it comes back and remember things will come back because it's going back to the original state of the image so here I'm also just gonna throw a forwards on there that will stop it so once it's gone it should actually be completely gone oh right I know why this is where I said this would be a bit problematic we also wanna make sure that it gets to there and then it stays there until the end so we can just throw that on there so the opacity ideally is coming up a little bit and then the whole thing will actually fade off I don't see this really happening yet but I think as we improve this we'll start seeing it actually come in it's just based on our view right now and improving on our range so ideally like we're only worried about wanting it to start as it exits the viewport we don't want the animation to start before that so we can just say animation range exit right so we're actually starting now at the 0% key frames we're at an opacity of 0.5 and now it should increase the opacity we get to 25% at one point and then the entire thing fades out perfect cool and now to really make this in Hammer at Home I think what we can do is come in and just add a scale here and make it get a lot bigger I don't know how big we wanna get it let's try a three on there and you can see it's growing, growing, growing and then it fades out as we do that and maybe we could also just come here and say that we do a transform origin of top because I think it's gonna make it just feel a little bit more natural if we do that or maybe a bottom even let's see how that looks and then it starts fading out as we come into the rest of it definitely something that could be mucked around that I'm not even sure maybe we could stay with the original because it's kinda cool that this text is coming up onto it but then we focus more on that text and it just sort of all fades away so the text fades off as the image becomes more obvious and then we get the rest of the article coming in and then we have that sort of fading helps with the rest of it this is just because we are learning stuff and I think the rest of it's looking pretty good as I was going through the final edit I realized I forgot to mention browser support and the polyfill that they have for this and the limitations of the polyfill and I thought that'd be very important to mention so we're gonna dive into that a little bit just because you can see here is the polyfill that I have open and we're gonna talk about that in a second but just right now the browser support for scroll timeline is not amazing as you can see here it is actually over 66% because Chrome just dominates the market basically which is pretty crazy it is behind a flag in Firefox as well so it is coming there but if I come right now and we take a look at this in Firefox it's not working these images aren't actually problematic but you can see here nothing's actually happening over here as well we have an issue and up here I don't have an image so I sort of wanna talk a little bit about this and just sort of the ways that you can still use this as a progressive enhancement because I think that's currently where it's best used just to add that little extra for users along the way so first of all if you do wanna use the polyfill it's really easy to do but there are some limitations to what it can do you probably don't wanna just copy the script and use it from here but I'm gonna do that for demo purposes and I'm gonna come in my code here and paste it in and now if we come to Firefox check this out it works and so that's kinda nice right but you'll notice here the animation range end isn't where we'd originally wanted it to be just because there are a few limitations to the animation range when it comes to using the view so you might have the images fading up over a different period of time I tried playing around with it I found an issue with the polyfill that's been filed so it's something that they're aware of but it's just a limitation of the polyfill I mean see up this top area it works really well so that's awesome the only thing with this though is it has to be inline styles so what I've actually done here is I've pulled all of the styles that were relevant to the scroll stuff and I've put those as the things that are inside of my inline style here but interestingly enough is if I were to wrap all of this inside the prefers reduced motion media query it breaks it and it just stops working and I'm not 100% sure why that is again it might be a bit of an issue with the polyfill cause you know it is a bit of an experimental thing that we're playing with here so instead of doing that I'm gonna save once again and that does break it over here and for the most part it's really not that big of a deal you know when you have things like this where they're you know I see my image and that's really what we're after so I see these images fading in as progressive enhancement up at the top though there's a problem where I can't see my image and the reason this is happening is because if we go and look at my styles here we have this the animation for my header image is linear and forwards meaning the animation is going to play it's going to do this animation as soon as the page loads it's easy forward so it does the animation it gets to the end of the animation and it stays on the last key frame and the last key frame for that has opacity of zero so whereas my images that we were fading in before were ending in an opacity of one that was perfect cause it's just ending at that point and it's staying there which is exactly what we want obviously here though with this forwards it ends at the zero and then that means that I get this which is definitely not what I want to get so the solution that we could do here is to use an at supports and this is a feature query so at supports and we support an animation timeline of view and if we don't or if we do support it then I'm going to bring all of this in here and of course that has to be for my header image so header image and save that and as long as this is in that at supports Firefox does not support it so Firefox sees that it goes I have no idea what that is so I'm just gonna bring in the image like I normally would with no animation on it and you could do this for all of them and just sort of add these scroll animations as a progressive enhancement you could play around with the polyfill as I said for some things you might not be able to get away with it for some things it works really well but if you do want the prefers reduce motion at least with my own experimentation with it I was having some issues if you know a way to fix that then let us know down in the comments but just that other limitation of the polyfill for now is that the styles do need to be in a style tag on the HTML page and not in an external style sheet from there and there's definitely some playing around and experimentation you might want to do with this as you're going through all of these different things I've tried to make this sort of a crash course to cover most of the different things you'd run into but there's probably a few things I've missed along the way here as well if there's stuff you know about these that I haven't talked about please leave a comment down below but if you'd like to see the video on where I created this animation which wasn't scrolling at the time it was just running but I made it so it was progressively enhanced so if somebody doesn't have JavaScript or if they're on a screen reader something like that that everything works perfectly fine but then we're sort of making all those different things come into play the way that we need to so we get sort of that animation going on and you can use it for different things it's often with like logos or something right that you have them slowly sliding by anyway, if you'd be curious about how I made that the video for it is right here for your viewing pleasure and with that I would like to thank my enablers of awesome web on demand, Andrew, Simon, Tim and Johnny as well as all my other patrons for their monthly support and of course until next time don't forget to make your corner of the internet just a little bit more awesome.