You Don't Need JavaScript For This - CSS ONLY Infinite Scroll

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
over the span of your entire online history you've probably visited websites with this cool looking animation these animations are called a Mary and all it is is elements laid out horizontally and that scroll infinitely on the surface this seems like a pretty simple animation however if you've ever tried to build this yourself then you know that it's deceptively difficult or at least difficult enough that you felt the need to use JavaScript and actually most tutorials you'll find on YouTube and on the web in general about this animation has you using JavaScript however in this video we're going to be building it with CSS only so no JavaScript only CSS now let's take a look at what we're going to be building this is what we're building it's the horizontal infinite scroll animation and for the purposes of this video I'm animating rectangle divs however this will work with whatever element you want and now before we start let's first visually go over how we're going to pull off this animation step by step with CSS only first we're going to need some divs then we're going to use a position of absolute to remove our divs from the normal flow of the document doing so resulted in all of our divs stacking up on top of one another then what we do is we position all of our divs to the right outside of the wrapper now we create our animation a very simple one all our animation does is moves all of our divs to the left and of of course we Loop it so that it animates infinitely now everything so far was pretty straightforward but this is where the magic happens currently all of our divs are animating at the same time they're all stacked up on top of each other and they're all moving to the left at the same time this is obviously not what we want so what we can do is give each individual div a different delay we tell each individual div to start its animation after a different delay and when we do this creates a staggered effect where each item starts its animation at a different time with each div having its own delay before starting its animation it's almost like our divs are all in line waiting for their turn to move this is how our animation is going to work under the hood and in the end this is going to be the end result in the description of this video you'll find a link to a cat pen where you can check out the final result for yourself and there's also going to be a link to a second code pen with the exact same animation but with two rows going in different directions similar to the thumbnail of this video to get started all I have is an index.html with an empty body element a styles.css with two rule sets and then back in my index.html we see I'm already importing my styles.css file inside my empty body element I'll add a div with a class called wrapper and inside of it I'll add eight div elements these eight div elements are going to be our rectangles and it doesn't have to be eight it can be any amount you want but in this video we're going to have eight rectangles I'll give each one of them a class called item and item 1 2 3 4 5 6 7 and 8 this is literally all we need for our HTML looking at our life server we see nothing is being displayed and this is because our divs are all empty so in my CSS I'll select our items by their class name of item and I'll give them a width of 200 pixels a height of 100 pixels a background color of red and a border radius of 6 pixels when I save and look at my live server we see our rectangles are being displayed back in my CSS I'll select a wrapper by its class name of wrapper and I'll give it a border of one pixel solid black when I save and look at my live server we see our black border however our wrapper is touching the edges of the viewport so back in my CSS I'll give our wrapper a width of 90% a Max width of 1,530 pixels and a margin in line of Auto looking at our live server we see this looks a lot better earlier I outlined step by step how we're going to build our animation the first step was adding our divs which we already did we added eight div elements the Second Step was removing our divs from the normal flow of the document with a position of absolute so in my CSS I'll give our items a position of absolute and we also need to give our wrapper a position of relative so that the positioning of absolute on our items can be relative to the wrapper if you don't understand this I have a whole video about CSS positioning on my channel looking at our live server we see our divs are now all stacked up on top of each other this is what we want however with our div now having a position of absolute our wrapper loses its height so back in my CSS I'll give my wrapper a height equal to the height of our items so a height of 100 pixels while I'm here I'll also give my wrapper a margin top of five RAM and this is just to add some space between the wrapper and the top of the viewport so now we've added our divs and we removed them from the document the next thing we need to do is position our divs outside of the wrapper so in my CSS I'll give my items the left property I want to position our divs exactly here outside of the wrapper and to its right this is very important it needs to be outside of the wrapper and I'm choosing the right side because that's where I want my animation to start so to position our divs out out set of the wrapper on its right side I'll set the left property to 100% when I save we see our divs are now outside of the wrapper and on the right exactly where we want them to be the next thing we need to do is create our animation however before we create it it's important to understand that where our divs are currently located is exactly where we want our animation to start however we also need to know where we want our divs to be when the animation ends our animation starts outside of the wrapper on its right so logically we want our animation to end outside of the wrapper on its left now that we've established where we want our animation to start and where we want our animation to end I'll create a key frame called scroll left and inside the curly braces we can Define where our animation starts and where our animation ends I'll add from curly braces and two curly braces from represents the beginning of the animation and two represents the end of the animation the only one we care about defining is the end of the animation we don't need to define the beginning of the animation because our divs are already exactly where we want them to start if our divs are already positioned where we want the animation to start then we don't need to Define where they start in our key frame so I'll remove from and its cly braces I'll open up the cly braces of two and what we need to do is Define where we want our divs to be positioned when the animation ends we said we wanted our divs to end outside of the wrapper and on its left so I'll add the left property and I'll set it to minus 200 pixels because 200 pixels is the width of our boxes so we say - 200 pixels in case you're confused about why we set it to minus 200 I'll demonstrate on my item rule set we see a left of 100% positions our divs to the right of our wrapper however if I replace it with zero and save we see our divs are now positioned at the beginning of the wrapper now when I set it to minus 200 pixels we see it positions our divs outside of the wrapper to its left this is also why it was important to define a position of relative on the wrapper otherwise these values wouldn't be relative to the wrapper I'll undo my changes and now that we have our key frame on my item rule set we need to define the animation properties I'll give it the animation name property and I'll set it to the name of our key frame so scroll left I'll add the animation duration property and I'll set it to 3 seconds I'll add the animation timing function property and I'll set it to linear and finally I'll add the animation iteration count property and I'll set it to infinite when I save and look at our live server we see we have our animation our animation starts outside of the wrapper from its right it ends outside of the wrapper from its left and of course it runs infinitely our animation works exactly as intended however we don't actually want to see our divs when they're outside of the wrapper we only want them to appear once they enter the wrapper and to do this is very simple in my CSS on my wrapper rule set I'll give it an overflow of hidden when I save and look at my life server we see now our divs only appear when they're inside of the wrapper this is another reason why we need a position of relative on our wrapper without it our overflow of hidden would not be hiding our divs with the position of absolute now this next part is where where the magic happens currently our animation is being applied on all our divs which are all stacked up on top of each other this is obviously not what we want we want our divs to animate sequentially and this is done by delaying the animation with a unique animation delay on each one of our divs when each individual div has its own unique animation delay it creates a staggered effect where each div starts its animation at a different time now hopefully this is easy to understand I'm hoping at this point everyone sees how giving a different delay to each one of our divs would create a sequential animation however the actual implementation of this concept is admittedly complicated because it requires mathematics so in my CSS we want to give each individual div its own unique animation delay to do this I'll head over to my index.html and we see we get save each div a class called item 1 item 2 item three and so on so back in my CSS I'll select our first div by its class name of item one and I'll give it the animation delay property before going any further our animation is going way too fast so on my animation duration property I'll change it from 3 seconds to 30 seconds when I save and look at my life server we see this looks a lot better back in my CSS because I want to give each div its own unique animation delay I need to select all of them so I'll copy our item one R set and I'll paste it seven more times because we have eight divs in total now I need to rename each rule set this one is item two item three 4 5 6 7 and8 back in my item one Ru set for our animation delay again we're going to use mathematics what I'm going to do is I'll write out the math first explaining as I go and then after it's all written I'll explain further so to do mathematics in CSS we use the calc notation and inside the parentheses we can do math the first thing I want is our animation duration divided by our total number of divs our animation duration is is 30 seconds and our total number of divs is 8 so I'll write 30 seconds / 8 then I'll do * 8 - 1 and I'll wrap both of these inside parentheses 8 is again our total number of divs and we're subtracting one because this is item one finally the last thing we need to do is time -1 now I know this is probably confusing and I'll explain it in a second but before I do I'll copy my entire calc function and I'll paste it on all of the remaining empty animation delay properties on item two I'll change one to two then on item three I'll change 1 to three item four 1 to 4 item 5 1 to 5 6 7 and 8 when I save and look at my life server we see see it worked we have our Marquee animation now back in my CSS I need to better explain how this works this entire calculation can be simplified as the duration of the animation relative to the total number of items times the unique delay for each item * minus1 which just transforms the result into a negative number 30 seconds divided by 8 determines how long each item's movement should take during the animation since there are eight items each item should take 1/8 of the total animation duration this calculation ensures that each item moves at a consistent speed and covers the entire distance from right to left within the total animation duration when you're writing this yourself you need to make sure that you're using the same number of seconds as the number of seconds you defined in your animation duration property they both have to be the same and then eight here is our total number of items so if you have more or less than 8 it needs to match your total number of items 8 - 1 calculates the unique delay for item 1 since item 1 is our first item we say 8 minus 1 however on item two we say that the delay is 8 - 2 and so on the 8 here is again our total number of items if you have more or less it needs to match your total number of items finally we have times - one all this does is converts the result of our calculation into a negative number so whatever the result is of our calculation doing time minus1 at the end converts the result into a negative number now to understand why we want the result of our calculation to be a negative number we need to see how the animation delay property interacts with negative numbers so to demonstrate I'll comment out all of our individual items and when I save we see our Dives are back to being stacked up on top of each other on my item R set I'll add an animation delay property and I'll set it to a negative number I'll set it to half of our animation duration so 15 seconds and I'll also make it a negative number when I save and look at my life server we see our div started their animation in the middle of the screen when I set it to minus 25 seconds we see now it started the animation towards the end and finally if I set it to minus 10 seconds we see it started the animation towards the start when you use a negative number on an animation delay two things happen first instead of a delay the animation plays instantaneously as if we had given it zero delay and second a negative number can control where the animation starts we want our animation to go go from right to left and the starting point of our animation is completely to the right outside of our wrapper and so if we don't convert our result into a negative number our Mary will start from the right and it'll take a Whole 30 seconds to cover the entire wrapper I'll undo my changes and just to demonstrate what would happen if we didn't have the times minus one I'll select it on each calculation and remove it when I save and look at my life server we see our animation starts from the right and slowly makes its way to the left now back in my CSS I'll bring back the times minus one and when I save and look at my life server we see instead of starting from the right and slowly making its way to the left our animation has already started and already covers the entire wrapper now while I'm here looking at my animation we see our divs are entering the wrapper from the right and they're also disappearing on the the left this is what we want however it would look a lot better if they were to fade in from the right and fade away from the left to do this is very simple back in my CSS on my wrapper rule set I'll add the mask image property now if you don't know what the mask image property is all it does is it hides a part of an element it is applied to so for example imagine you had two images the first image is a landscape and the second image is a St star then you make the first image a background image to an element and for the second image you assign it as a value to the mask image property when I do we see our second image which was assigned to the mask image property masked our background image and this is because the mask image property hides part of an element it is applied to now that you understand how the mask image property works we can use it to create our Fade Out effect however instead of using an image we're going to use a linear gradient on my mask image property I'll set it to the linear gradient function and for the first argument I'll set it to to WR this indicates that our gradient should be horizontal then I'll Define four rgba functions the first will be 000000 0 the second will be 0 01 and 20% gradient transparency these first two rgba functions Define the gradient for the left side the last two rgba functions to find the gradient for the right side I'll set the third rgba function to 00001 and 80% gradient transparency and I'll set the last rgba function to 000000 I'll also remove the border from our wrapper we don't need it anymore when I save and look at my life server we see this looks perfect however there's one last thing we need to do our animation isn't actually responsive and we can see this when I resize the page we see as I resize the page the gaps between each div get smaller and smaller until eventually they're all touching each other the reason this is happening is because if we look at our CSS on our left property we see I'm using a percentage for my value when I resize the page 100% changes relative to the width of the viewport and this constantly changes as I resize the page so what we need to do is use a pixel value for our pixel value I want the width of our divs times the total number of divs in our animation I'll replace 100% for the calc notation and inside the parentheses I'll say 200 pixels * 8 this equals 1,600 pixels when I save and look at my life server we see this fixed our problem when I keep resizing the page down we see our animation stays responsive however before I resize the page up to full screen in my CSS on my wrapper R set I'll comment out the width and the max width properties back on my live server I'll resize the page up to full screen and we see our animation is responsive on small to medium screens however when we reach full screen our animation doesn't animate all the way to the right we see there's always a big gap on the right side of the page and we also see our divs appearing which isn't something we want so our new left property is only responsive for smaller screens and our old left property of 100% was only responsive for larger screens how do we fix this well we could use a media C that checks the width of the viewport and changes the value of our left property accordingly however there's an even better solution back in my CSS on my left property I'll wrap the calc function inside the max function our Cal function is now the first argument to the max function and I want to give it a second argument so I'll add a comma and for our second argument I'll say 100% if you're not familiar with the max function all it does is it applies the biggest argument at any given time we're giving it two arguments and so whichever one out of these two arguments happens to be the biggest is the one that's going to be applied our first argument is 200 pixels * 8 this results in 1,600 pixels and it'll always be 1,600 pixels however our second argument is a percentage whenever I resize the page this changes the width of our wrapper when the page is full screen the wrapper is wider than 1,600 pixels and so our Max function applies our second argument however when we resize the page down to smaller viewports 100% becomes smaller than our first argument and when that happens our first argument is what gets applied so let's see if this worked on my live server we see on full screen our animation looks perfect and when I resize the page down we see our animation still looks perfect this means using the max function fixed our problem and now our animation is is fully responsive without the need of any mediocre back in my CSS on my wrapper R set I'll bring back the width and Max with property when I save and look at my life server we see our animation is finished this CSS video was a little more advanced however it's surprising how powerful CSS is and what it can accomplish especially considering the fact that typically this animation is built with JavaScript I think this CSS only solution is cleaner if you enjoyed this video consider giving it a like subscribe and thanks for watching
Info
Channel: Slaying The Dragon
Views: 55,722
Rating: undefined out of 5
Keywords: CSS, Marquee, Infinite scroll, Slaying The Dragon, CSS Marquee
Id: Reu0hHbis5w
Channel Id: undefined
Length: 23min 35sec (1415 seconds)
Published: Thu May 23 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.