 Linking animations to our scroll position on a page has never been easier thanks to the web animations API and scroll timeline, making animations like this one a breeze. Hello my front-end friends, thank you so much for coming to join me once again, and if you're new here my name is Kevin, and here at my channel I help you fall madly, deeply in love with CSS, but today we're taking a bit of a different path because we're actually going to be exploring some JavaScript. Over on my Discord it was suggested that I take a look at making scroll-based animations, and with how easy it is to do with the web animations API and scroll timeline now it seemed like a really good time to jump in and take a look at that. First we're going to do a very simple thing which you see all over the place which is those scroll position trackers that go across the top of a page just to understand a little bit on how all of this works and then we're going to step things up and explore a little bit more of what we can do by making those images that can slide in and appear and really do anything you want with those types of things. Alright so as you can see I've already written some HTML here but it's just a whole bunch of content basically and I put a couple of pictures in here that we can play with and it's from the site actually it's the same image that was asked if I could recreate this with. But yeah we're going to do one extra line of HTML here just to get things started so I'm going to do a div of scroll tracker just like that and we're just going to leave it blank. With that div in place this is just really for decorative purposes but let's come over to here and we're going to do my scroll tracker and we're going to let's start by giving this a height of we'll say 0.5 a rem we'll give it a background color and that could be I have some variable setup so I'm just going to color primary 400 which should give it a blue color and there it is. But we do want to do one more thing with this let's give this a position of fixed and the reason I'm doing position fixed is because when I scroll I want to make sure that it always stays in view and because I'm going to put a position fixed on this this position fixed will actually make right now the default width is 100% it's going to shrink down to zero so if I hit save it seems to vanish we could just give it a width of 100% but what I'm going to say is inset because I want to set a top of zero anyway so I'm going to do an inset of zero zero auto and inset is a shorthand for top bottom left and right and so this is my top and it's like margin so with three properties that would be my left and my right and then the auto of zero just means sort of ignore the bottom property almost and there we go we get my scroll tracker that's there but obviously we want this to actually track our position now interestingly this is something that I did recently with CSS only using scroll timeline and what we're looking at today is actually built on the same technology that makes the scroll timeline possible the only issue is scroll timeline right now has basically no support other than like on the cutting edge browsers and behind flags and things like that which isn't very realistic and so this is very similar in how it functions though we're going to be doing everything in javascript and even on the javascript side the support isn't fantastic but we have a polyfill that we're going to be able to use so the first thing I'm going to do is actually just paste in the link to the polyfill here so I'm just importing this directly and I'll put a link to this polyfill there which has a little bit more information on how you could use it within your projects but for a simple demo like this just importing it at the top of my javascript is perfect though if we do want to bring it in as an import statement like this this does have to be a module so luckily it's easy enough to do you just come into here and you can write type is equal to module and just to show you if I hit save now nothing should be a problem let's go look in our console there's no errors if actually let's not go there let's save this file too if I come here and I remove the type equals module you'll see that I we get a syntax error so just if you want to have that import statement at the top just make sure you have that so that it can work and so let's close that and we can jump back on over into our javascript all right and now we get to jump into the fun bits and if you follow me you might not be doing a lot of javascript so if that's the case I will try and take things slow enough because even for me javascript isn't always the most comfortable thing in the world at least compared to css so first I'm going to make a constant scroll tracker just so we can have you know we need to tell it what we're going to be playing with here so let's do a document dot query selector and on the query selector that is going to be for my scroll tracker right that should do that the trick on that one and then we want to use this somehow so before we do anything with the scroll tracker what I'm going to do is actually because we will be writing about a javascript it does take up more room than css so let's make that a little bigger and the first thing we want to do I'm going to create a constant I'm going to call this scroll tracking timeline the name of it is whatever you want to name it here but what's important here is that we use a new and it's going to be a capital s scroll timeline and then we're going to have an object so I'm going to open and close my curly braces and inside of there we have a few different things that we can define in this case we're actually going to be sticking with the defaults but we're I'm still going to show the different options that we have here so you have a source and by default the source is the entire viewport because that's your scrolling element if you wanted to do this within a different element that does scroll this has to be something that scrolls so if you wanted to do something different that scrolls you could list out the source here what this actually is we're in your document dot scrolling element another one that we can have here is our orientation orientation and we have block or inline so do you want it to be block is going to be up and down scrolling and if you wanted to look for inline so left to right scrolling or horizontal scrolling you could just switch that there and the last thing we're going to do is what's the range that we're actually looking at now for that range it's called scroll offsets and the scroll offsets we're going to have to tell it the starting point and the ending point and for this you just put it inside your square brackets and there's different ways we can do this i'm going to do capital all capital css dot per cent and put a zero and then we'll put a comma and then do css dot per cent and do 100 so we're checking from zero all the way to 100 but we'll sort of look at what this does a little bit in a second the problem right now is we've set this up we have a scroll timeline so it's going to be paying attention to our scrolling from the top all the way down to the bottom of our page looking at the block orientation and again of the entire document and these two again we could actually omit those and it should work just fine but we're looking at a demo so i'll leave those on there but what we need to do now is we actually have to use this somewhere to actually get this to work so to do that we want to attach it to our scroll tracker that we have right here so for this we're going to do scroll tracker tracker come on there we go dot animate nice and easy and we're going to come in here i'm going to push return and then open and close some curly braces because we have a couple of different objects that we're going to be working on here and inside this first one what we want to do is say what we're actually going to be animating what are the properties we're doing so the first property and with a tracker like this you could be animating the width you could also be doing if we'd set this up a little bit differently we could animate the width if you wanted to do it by using your left and your right whatever it is because scroll based animation i don't know actually what the implications are of animating things that normally we'd be a little bit more concerned about so that's something to look into but i think like the idea of like a buttery smooth animation might be a bit less important here since it's really linked to your scrolling positions but what we're going to do for this one is i'm just going to do a trend i'm going to say we're going to animate our transform property and then we're going to open and close square brackets and i want to tell it what we're at a little bit like we did with our scroll offsets we're going to say what the beginning transform is and what the end transform is so here we're going to say scale x of zero and then i'm going to put scale x and i made a mistake here of one and the mistake for that is you just want to make sure that these are wrapped inside of parentheses not parentheses of quotations so there we go and so that's it up now we as i said we will have multiple objects here so i'm going to do a comma and then we're going to open and close another set of curly braces and inside this one it might seem a little bit silly but you're going to need a duration now this animate is not part of only the scroll timeline that we're looking at which is right here the new scroll timeline this is part of the web animations api so durations here could be used for other things it's not necessarily to link it to scroll-based animations and just know it's always in milliseconds as you would expect with javascript but really the duration has no impact here since we're going to be linking it but we're going to throw one on there anyway and the other thing we want is to say what the timeline is and in this case it's my scroll tracking timeline that we created right here and with that we should be good to go except i think block here actually needs to be inside quotation marks as well i do apologize for that that's it save and it's still not working because scroll timeline look advantage there we go that's good news and it's growing there we go a few little hiccups there but everything's working except it's kind of weird that it's growing from the middle and not from the left so kind of weird so let's come back to my css and i guess i lied to you a little bit and that we won't be writing any just a little bit um let's just do a transform origin of left that should fix the whole problem and that should give us there we go as we scroll down it goes and we reach the bottom of the page it's full and when we get to the top of the page we don't have anything there and as i said we can play around with some of the numbers so maybe you'd have a footer and you don't care about the footer you know so you could set this to 80% let's just say and then it will track it when you get to 80% of the way down the page it's showing that it's full and of course you know you have something at the top that you don't want it to count so at the very beginning there's nothing but then once i get past a certain point that comes in or maybe you don't want this as a percentage you can put that as pixels and i could say 250 pixels and so now it will only start once i get to 250 pixels it will start tracking so you know you can even get javascript to get the height of this and then use that as the value that's coming in here whatever you want i'm gonna just do it for my whole page so we'll leave that as a percent just like that all right and with that done now let's see how we can take this the next step and look at how we can animate these images we're not watching the whole page but we're going to watch for the specific image locations so the first thing we're going to do one image first and then look at how we can have it apply to as many as we want and we're sort of exploring going to explore different sort of properties and different things that we can do with this as we go through on this one so the first thing we're going to go to my index and you can see i have this image in here which has my image rotate in class so the first thing we should do is get that image and so we're going to do a const of we'll call it animated image is going to be equal to document dot query selector and we'll choose that dot image rotate rotate in just like that and so we've selected this image that's right here and we can do very similar we're going to set up a timeline first and then we're going to animate it one big difference is what we're going to do with our scroll offsets so let's start by const and we'll call it animated image timeline is equal to a new scroll timeline and in this we're going to have our well we don't need to have the source or the orientation as i said when we did this these are defaults so i'm just going to go in with my scroll offsets and for the scroll offsets this time we're actually going to do something a little different like i said and we're going to look at two different approaches i'm going to look at the first one which is going to watch the image itself enter the viewport and leave the viewport and that's actually going to work a lot like how an intersection observer works um which is probably the last time i talked in depth about javascript but uh yeah we're going to do that first and i'll look at a limitation of that and then a more involved solution that might be closer to what you actually want to do and so here on my scroll offsets what we can do is we're going to open and close some curly braces because what we can do now is actually define a target so my target in this case is going to be my animated image we're going to have an edge and for now just trust me on this one i'm going to do end and we're going to do a threshold threshold of one and i'm going to duplicate this line here and don't worry i'm going to explain it all more in a second we're going to put a start here now what's interesting about this is this is actually when the animation will start and this is when it's going to end so it might seem a little bit strange having the edge as a start and an end but trust me on it this is what we want and as i said we'll explore this in a little bit more detail and i just see a syntax error here because i forgot my comma at the end of that line so that should be enough as long as i didn't make any other typos here and actually i did these should be also inside of quotation marks so there we go we get my threshold of one on both of those and thresholds a scale of zero to one but we'll look at that more but if you're used to intersection observers that is you you're probably familiar with that what that is and just like we hate to set up our scroll tracker animation here we're going to do the same thing here so we're going to do my animated image animate open and close our parentheses and then we can open and close my curly braces and we're going to do multiple different properties rather than just one but we're going to start with one and then add the other ones on top and the first thing is i'm going to do a transform and we're going to go from a rotate rotate of x on the x axis of 45 degrees which is going to rotate the image this way now for this on the transform we actually need to do a bit more for it to look good but i'll come back to that in a second so let's just see what this is going to do first and then here rotate to a zero and yeah that should work perfectly then let's come here and do a comma i open it another set of curly braces and my duration should be a one and my timeline in this case will be my image what do we call it animated image whoops animated image timeline and so we should be able to hit save on that no i see something changed on my image already so that's a good sign and now as i scroll you can see the image is sort of unsquishing itself which isn't exactly what we wanted but at least it's doing something um and so let's start with that and what you'll notice it's not nothing's happening and now all of a sudden it starts and maybe we should do this even more let's do 90 degrees so or 180 so that should make it you know 180 shouldn't yeah there we go 90 makes it vanish so it's completely flat and then as we scroll up it's flattening itself out and when the top of the image reaches the top of the viewport it will be completely done and to explain how this is working i'm actually going to bring in this here which is a code panel i'll link this in the description as well by bramis which shows we have a starting edge and our ending edge so start we do start and then end and then we have the threshold and a threshold of zero means the animation will start when the element has touched the ending edge or if we look at the starting edge it's as soon as the element has left completely the viewport like as soon as it's touching the top of the viewport but completely out if we move this threshold you can see how it's moving it into the viewport which is sort of the blue area that we have here and then when we get to here that means when the threshold is one so it's completely within the viewport and it's touching the starting edge um and so what this is doing so that's why we're having the animation start at the ending edge because that's the bottom of the viewport and we're having the animation finish at the start of our viewport which is at the very top so it might sound a little strange but it's sort of it makes sense when you look at it that way so here if we actually change this to a zero and a zero that means the animation is starting now even though the image isn't on the screen yet because it's you know it's starting a little bit earlier and then here it's finishing it's still animating until it's all the way off the screen so I think a lot of the time you probably want a threshold of one though it's possible you want something a little different than that and so to improve this a little bit what I'm going to do is I'm going to come here and add perspective perspective and I'm doing it here I'm going actually keeping my I'm going to keep the perspective the same on both of these so transform perspective and this is just going to make it actually look sort of 3d-ish and this is a number I find you just have to play with I'm not very good at this um so let's add a perspective there and a perspective here and so now you can see it actually gets more of like this here it's completely flat and you know it looks more like you'd expect it to look right uh for this type of thing so it's completely linked to the scrolling of my viewport which is cool now I think it's a little too much so let's I'm going to start it at 45 so when it enters the viewport it's sort of tilted a little bit as soon as it comes in a bit more it starts tilting and then it finishes at the top and to make it a little bit nicer we have transform here but we could also come in and say opacity and my opacity we can have it go from a zero to an opacity of one and so now if we look at it it's completely gone and then as I scroll the opacity will come in and it will rotate up and yeah I just think it looks a little bit nicer with the opacity maybe you could actually start it at like a 0.5 or something just so it's not completely vanished when it comes in it's a little bit there and actually maybe here the threshold of zero and this being at zero uh could could potentially be better so it's starting to fade in as soon as it enters the viewport but then it's completely in view and completely finished by the time it reaches the top of the viewport now what you might actually like is that it's completely finished the animation here but before we worry about that let's see how we could actually get this to work over multiple images and I'm not saying this is the animation that you'd necessarily want to do over multiple images I'm lucky to do that it's actually really easy uh it's just here let's come up and here I have my animated image let's make this plural so it's a bit better and here I'm going to do a query selector all so it's selecting all of my images with that class which I have this one and there is a another one here so we have my two identical images in this case um and this will also show us a little bit of a limitation of the scroll timeline here that we have but uh I'll get to that in a second uh but basically everything here can stay exactly the same the only difference is right here so the first thing we're going to do is let's say my animated images and we're going to say for each and for each one of the image image for each image inside of my animated images we want to do something so we'll throw an arrow function in here and let's there we go perfect and now what I'm going to do is I'm just going to grab this here and drop it right in here but instead of my animated image here and then I can bring each one of those down right here uh I'm just going to save to format the code a little bit better and I'm just going to then take all of this we can take all of that and I'll show you actually we're gonna let's take all of this first and just to make this actually work we can bring it all into here and now it should work for both of my images and here we also this one just I had that as animated image before so we just want to actually remove all of that and make that my image as well so for each image we're going to have this animation running that's using this scroll timeline right here and the only reason that I'm putting this inside the for each here is just so the target is it's creating a new target for all of the images that are getting that class and now we can see that it's working for both of those images so as I go down there's one there's the other one perfect now one thing you could do if you don't like this idea of having this here and having this here is we can actually take all of this for it says new scroll timeline and select all of that and so let's take that and I'm going to comment out this entire section and then when we have a timeline here instead of looking back at that timeline we can actually put all of that here where you actually just make a new timeline right there so if I hit save now it's still working just as it was before it's exactly the same thing that we just had so if we you know you don't have too much going on over here it could be a simpler way to do it the nice thing with having these is sometimes you'll have multiple different objects using or sharing one timeline so having this on its own here lets you point multiple different things at it whereas in this situation it's very stuck to being only for the image and that's it and as I said there's one more thing which is we don't always want it to start here maybe I only want the animation to start once we're past this threshold of one or we want it to finish before we're at this threshold of one over here and with the threshold we can't actually do that so I'm going to comment out these scroll offsets here and I'm going to bring in a very new scroll offsets and it's going to take a little bit of a similar approach than we did here with our CSS percentages but it's going to be a little bit more complex so actually the first thing for each one of these images we are going to get something so what I'm going to do is create a new variable here called image offset top and sometimes I get questions and here const or let const works because it's doing it for each image individually so it can be a const it doesn't get redefined anywhere and so for that my image offset top is going to be equal to the image and we can just do an offset top and then I'm also going to do a const of image height and that's going to be equal to my offset height just like that so that should give me those values for both images that we have and as I said that's just because we're going to use these in a bit of a different way so here what what I want to do is I'm actually going to say that the first offset we're going to do a CSS pixel but we're going to use all of these so we want to get my image offset top plus my image height and we're going to do those together minus my window dot inner height and so that's where the start and we'll explain this in a second and let's just put a comma here and then the second one is going to be a CSS pixel as well and for this one I'm just going to say my image offset top and we're going to change these in a second but that should work there we go so you can see that's working and okay let's explain what this is doing so we're saying my image offset top so how far the image is from the very top of the viewport so from here all the way down to the top of the image is this this one right here then we're adding my image height to it um actually what I mean if we didn't do it with the image height here it'd be the same as having a threshold of zero it would kick in as soon as the image is at the very bottom whereas now what I've done is pretty much replicated this idea of a threshold of one as soon as the entire image has entered the viewport it's going to start and then here the offset image offset top is the same thing that we had right here so you might be saying Kevin you just did a whole bunch of stuff to replicate what we had here and I did it's true but the the one advantage we have here is then you could throw extra numbers in here so for example if I wanted it to end 200 pixels before the top I could just do a minus 200 so let's hit save on that and now we'll see the animation is completely done here so we're not getting to the threshold of one we're getting to a threshold of like minus 200 and then we can do that same thing over here I don't know if this would be a plus or a minus let's try plus 200 and let's just see yeah so now it's getting it's doing nothing and then once we're 200 pixels past the entire image the bottom of the image is 200 pixels away from the bottom then it's going to start that animation and so it's not perfect by any means I don't think I necessarily want it to start there so even you can have it start before it even enters the viewport with a minus there so it's starting it's already going and then it's finished before we get to there and maybe we'll make that a minus 300 so that way you sort of get the instead of having to wait until in this case we're revealing it at the very top we're allowing it to happen much much sooner and so just a couple of ideas there that you could do but this does show the one other limitation of this is as I scroll back and forth it's always running the animation and that could be a little bit annoying you might want this to you know if you're doing it for certain reveals it could be a nice thing or if you're doing it for your tracker up here it could be a good thing if you're doing this for image things that slide in and then they're sliding in and then somebody scrolls up and they slide away and they slide back in and they slide away that could actually be kind of annoying and you don't necessarily want to be linking the sliding in animation to the scrolling itself like we are here like this is kind of cool because it's really linked to that because the rotation of the image is based on that that might be something you want if you just want something to appear on the screen once it gets to the right place that's where an intersection observer would come in and if you'd like to know more about intersection observers or you'd like to know how this is all going to work with css only because this will be a css only thing at one point once browser support gets there well i've looked at both of those and you can see those videos right here and with that i want to say a really big thank you to my supporters of awesome over on patreon jan johnny steward tim and simon as well as all my other patrons for their monthly support and of course until next time don't forget to make your corner the internet just a little bit more awesome