 Hi there my friend and friends. Particle animations can be pretty awesome, right? They can be used for big in-your-face effects, small little micro interactions, and everything in between. Often we rely on JavaScript to be able to do these particle effects and animations, and often even then we're using a third party tool just to make our life a little bit easier. But you can make really awesome 3D particle animations with just CSS like my friend Emmett Sheen did with this firework animation that we can see right here. And not only does it look really good, you can use a lot of techniques to also make it performant as well. Now if you know me, you know I'm sort of decent at writing CSS, but animations are definitely not my strong point. But luckily Emmett was kind enough to come and join me to discuss how we could do some particle animations. We're going to be doing it this time by looking at the school laser effect where we're going to have a 3D space and cuts through the surface of something that's going to fall away and the whole time that's happening we have these like flamey sparks shooting off of it. And during all of this, not only do we learn the cool stuff that's involved in all of that, but Emmett shares some really good just general animation tips and tricks. And there's just so many great takeaways that Emmett shared while he taught me how to do this. And so we're going to kick things off with Emmett explaining how he got the inspiration for even thinking about doing stuff like this and then diving right into how we can get started with it. So this whole idea started like a couple of weeks ago. I talked to a guy that asked me the question that you probably know better than me. How do I improve myself in CSS? How do I get better? And one of the things I suggested was let's do the challenges like I code this or like the code pen challenge. And we talked about the code pen challenge. And this month's code pen challenge is about particles. And he said, well, you can't do particle animations in CSS. And I said, well, of course you can. And that day I did like this animation of fireworks because that week was the fireworks theme. And yeah, you can absolutely do particles animations with CSS. And that is what we're going to do today. And we're going to look at a lot of nice things like syncing animations. And because the whole idea of particle is working with a large number of elements, we're going to look at a nice little sass loop. And we're going to even add a little spice with some random. And we're going to look at some random things. Yeah, so let's dive in. Do you want to just go over the CSS that we have right now in the body? Yeah, so we have a background color, the height. So we're just, you know, the min height with the grid place items is going to keep everything we do in the center of the screen. So now the scene is just like an invisible dot in the center of the screen. And what the other thing that we have is obviously perspective because we're going to use 3D. So we need a perspective. And because we want this perspective, the body is like the perspective container, but we want the perspective to be on all of the children and the descendants of the children. So we're going to give this everything that is not empty, a transform style of preserved 3D. So it would preserve the vanishing point of the father. Yeah, and that's it. And this is the scene is in position relative. And the animation that we're going to do today, because we talked about what would be cool to do with particles and what is always cool? Lasers. Of course. So we're going to do like a laser, a simple laser that is like cutting something and where it cut. So we're going to see a lot of sparks and that's those spark would be made out of particles, obviously. Awesome. So let's start with the HTML. And we're going to add like two basic elements. First, let's add the laser, the laser that's going to cut. And we're going to add like a panel or a div or something, just something for the laser to cut. Let's give it a class of panel. It's okay. Yeah, that's it for now. We're going to do four things. The laser, the panel, the sparks, obviously that's going to be the main part and then we're going to add like a falling part after the laser cuts the panel. Going to add something that falls. Yeah, so let's go to the CSS. Do you want me to do it, by the way? If you're sick of writing code, just tell me. Okay, sounds good. If I'm struggling at all, feel free to like fix any of my mistakes and stuff too. Cool. Let's add a simple class. We're going to start with a laser, okay? We're going to say laser. And by the way, do you know what the initials of laser is? No, I know it stands for something and I never remember what it is. It's a trivial question that like in pub quizzes, it's like simplification by stimulated emission of radiation. So we're going to give it a position of absolute because we want to position it absolute according to the fatter. And it's going to be a laser. So it's going to be like a thin long line. And we can give it a width and a height or we can use or we can use an inset. Yeah, so if you give an inset with a negative value, like for example, if you give like minus 10 pixels, so we're going to have if you give it like a background color white, for example. So now we can see that we have like a square, yeah, of a 20 pixel by 20 pixel because it moves 10 pixels to its direction. Okay, so yeah, because the parent is basically a zero by zero in the middle, we're pulling it outwards. As I said, the scene is like an invisible point in the center of the screen. And the laser is inset minus 10 pixels in either direction. So it's a nice way to center things if you want them to be square or round or something. But if you want them to be long, so we can add into the inset two values. So let's add to the first value one want to make it long. So let's make it like 50 V V H. We can even make it more. Yeah. And when it seems so let's make it like one pixel. Oh, this needs to be negative, right? Yeah, it's a very common mistake. Yeah, so, but laser, let's think the background color red, because you know, it's a laser. But laser also have it's a light. So we're going to use like like create like a neon light. And the trick to create those lights are actually by layering box shadows. So you can create just a regular box shadow of like zero zero and let's say five pixels of red. And then, yeah, and then you can actually, yeah, just copy it and then exactly. And and as for the values, I normally do something like some sort of like, like not not a complete series, but not like if it's five, 10, so it's 15, 25, 40 and so on, because it's one added the last one. Yes, we can add one 40. And maybe the color itself in the middle, not like red, make it like a light red or coral or something like that. No, no, the color of the background itself. Oh, right, right, right. So this is our laser, but this laser needs to cut something. So let's create another class. We're going to call it how do you call it? I did panel there. Yeah. And that panel also going to have position absolute. Now that panel is going to be let's let's do let's give it a width of a width and a height, but I want to be very, very, very wide because I want to be out of the screen. So let's say, for example, like a hundred VH the width and the height, let's say 120 pixels. And the reason I chosen 120 pixels, because later I'm going to give each one of those pixels a different, different elements. So I don't want it to be too wide. I don't want to be too near 120 pixel 100 and you can we can go 140 160. But this is sounds like a good, good measurement. Yeah, so we can already see it. Okay, but we do need to move it a bit. First of all, we need to move it to the left. We need to move it up so it would be in the center of the screen. Okay, we can do it by just modifying the top and left of the panel. So the top let's say, so the top needs to be minus 60 because it's half of the minus 120 pixels. And the left, let's say, minus 120 pixels. So the piece that is out that is left of the of the laser, the piece that is getting cut off is square. Right. Yep. Right. Okay. So but now this is right now it's parallel to the screen parallel to the laser, we need to rotate it. Okay, 90 degrees. So let's add rotate and we're going to need use an individual transform. That is rotate 90 degrees on the x axis. So no, so you need to add the word letter x before rotate x. No, no, no. No. Here x 90 degrees. I always forget how to do it with the single ones. Yep. Yep. Exactly. Yeah. Okay. Okay. So so now actually we don't see the panel because we don't see it because it's completely flat. It has no depth. So it's it's it's it's it's height is zero. So we can rotate it a bit less than 90 but instead we're going to leave it 90. What we're going to do is actually going to rotate the scene. I'm wrapping everything in the scene because this scene is like a camera. So imagine that this this side is is the panel and this side is the camera and want to move the camera up but in CSS we can't move the camera up. What we can do is actually rotate this scene down. So we're going to give the scene a transform and we're not going to not going to use the rotate the individual transform here because we're going to give it a rotate x of minus 30 degrees for example but I also want to rotate it on the y axis a bit. So we're going to give it a rotate y and if you want to give two rotation like on two axises so doing it in the individual transform is you need to use vectors because you use like a translate a rotate 3d parallel. So it's much less reasonable. So whenever I need to rotate something on two axes I'm still using transform. Would you do rotate x and y or would you just do it all within a rotate and put both values? No, you would do the two. No, no, yeah. Just to make it more readable. Yeah, if you don't put the rotate without the x and y so it's actually right. Then it goes. Yes. Yeah, it's not parallel. It's not like a translate. Yeah. So let's do like 30 pixels 30 degrees. Yeah, so now we can see the panel. Okay, so two things we can see we can actually see the the right end of the panel. So let's make the panel a bit longer like I don't know 200 vh or something and the laser. Yeah, and the laser because it's we can see it's and so I'm going to change it to like 100 vh just just just so we won't see the the end. Okay. That's let's start moving things. Nice. The first thing that we need to move is the laser. So let's give it an animation. No, no. Oh, I was gonna make some keyframes but go for it. I'll let you do this part because you'll be okay. So let's start with with a simple animation. Let's call it laser because it's laser. And we're going to add a variable and we're going to add like a constant variable. So we're going to use a SAS variable of duration. So we obviously need to add this variable like up here. Let's say 10 seconds. So later we can change it and everything is going to change accordingly. Okay. So but right now the duration is 10 seconds. And obviously I want it to be infinite because I wanted to look over and over again. And I want the movement to be linear because it's no it's like a laser. So let's make the the movement linear. Okay. So now yes, we can actually go and create the keyframes. I like to create the keyframe things right here. But do you want to create them outside? It's but I guess it just because we're using SAS we can nest it in. But the one thing I will ask is just if somebody, I know we're going to use some SAS for some loops and other stuff later on, but is there an advantage to using a SAS variable here instead of using a custom property? Yes. Because later on when we use we're going to use a loop a SAS loop and we're going to use some mathematical calculation inside of that SAS loop and doing that calculation is going to be much easier with a SAS variable. Perfect. That's just that's the only reason. Yeah. So let's start. We're going to do a few things for the for the laser. We want the laser to start at one end and move to the other end of the panel obviously. So it's actually moving on the z-axis and we actually, let's start with the movement. But we want to do two things because we don't want the movement back. So I want the opacity to change the opacity in the beginning. So let's actually start with the opacity. So the opacity is zero. And let's say that in 10% the opacity is going to be one. But the other thing that I'm going to do is I'm going to translate it. Should I use the transform or the transition? It's up to you. I've started doing just you exactly. Yeah. I asked you the transition but as I said I'm doing a transition on the z-axis. So the z-axis is the third value. So it's x, zero, y, zero and z. We're going to start at minus let's say 120 pixels. Oh, translate. Yeah. Oh my God. I was staring at it going, wait, why isn't it? There we go. Okay. Yeah. So now it's here and we can see the start. And then at some point I want the movement to be 60% of the time. Okay. The reason I'm selecting 60% is because 60% is divided by four nicely. We're going to talk about the math a bit later. So 60 plus 10 is 70%. So at 70% it's going to be at plus 120 pixels. Okay. Reach the other side. Yes. Yep. There we go. And it goes all the way through. All the way through. And at 80 I'm going to just add the opacity to zero and I'm going to leave it the same all the way to 101. Okay. So now what we have at the laser, it starts at zero. It stays there for one second, for 10%. So it's one second while the opacity is moving to one. And then it's taking 60%, 60 seconds to go to the other side. The total travel distance is 240 pixels, right? Because it's from minus 120 to top 120. And then it's just fading out. But we do need to know the exact moment to sync up all the other animation, the exact moment when the laser touches the panel and the exact moment that it leaves the panel. That's why I used 60% because the laser touches the panels after 60 pixels. So it's a quarter of the time. A quarter of the time is 15%. So we know that it's going to hit the panel in 25%. Okay. So we're going to use it. And we're actually going to add another animation right here on the laser because I want the laser when it hits the panel, I want to remove the bottom part. Right. Yes. We don't want the bottom part when it's removed. So we can do it in many ways. I can trace it and move it, but I'm actually going to just use scale to scale it up. Okay. So let's add another animation here. Let's add laser scale. I'm going to have exactly the same duration. Oops. Infinite. And I'm actually going to leave the timing function, the linear, the timing function. I'm going to leave the timing function blank for now. And this will go to the keyframes. And the keyframes for you're following me. So in 0%, obviously, the scale needs to be one. But we said that the laser hits the panel at 25%, right? So at 25%, the scales need to be zero. Okay. But I don't want the movement to be, we can... Why is it saying that I have a mistake here? And the fops duration. Okay. So now we can actually see the movement out. So we can, we need to do two things. First of all, we need to add the transform origin to the top because the transform origin is in the top. But the second thing, we can see that the movement is... Why is it moved? Oh, I did it to zero. It's going to be 0.5. But we can actually see the movement. I don't want to see the movement. I want it to jump. I want it to be instantly. And in order to make it instantly, I'm going to add a timing function of step 10. So now you can see it's going to be full up until 25%. Then it's moving in the same... Like instantly to... Yeah. And we're going to leave it there for 55% because it's there all the way to the end. And in 60, it's back to one. But I want the movement from 55% to 60% to actually going to... I want to see the movement. I don't want it to be instantly. So how do I change the timing function in the middle of animation? We actually, we can add an animation timing function here and add like an ease in out. We can see the laser starts at the beginning and it instantly jumps to half of the size. And when it goes down... Nice. I never knew that you could change the timing function within animation. You knew because we did it in the last video. I don't remember that. But here's the thing. Everybody forget that you can actually animate the timing function. We're going to do it again later on. Awesome. It's fun and you can absolutely do it. And if you're working with animations, sometimes you just need to animate the timing function. Yeah. So we have the laser. I think that's okay. Let's go to the main part. Let's go to the sparks. So let's go back to the HTML. And in the HTML, I'm going to add sparks. And in the sparks, as I said, the reason people saying that it's hard to do particle animations with CSS because the concept of particle animation is using particles, a lot of element. And doing it with CSS meaning that you need a lot of elements. So the performance might be problematic. But in these types of animations, because we're only using transform, only using opacity, and we're only using 120 elements, it's going to look pretty okay in most phones, I think. So we're going to add like 120 elements here because we have 120 pixels. I want the spark for each pixel that it goes through. Let's have it... We can do it like a div or anything, but let's make an i. And as I said, 120. So now we have 120 sparks. Right? Yeah. Perfect. Perfect. And that's it. Let's go to the CSS. So sparks. Again, obviously it's going to be a position absolute. So now the spark is just like a little dot in the middle of the panel, right? And all the i's inside of them is going to be obviously position absolute, according to them. We're going to use the same inset trick, let's say a minus 16, let's say 16 pixels. I don't know, something like that. We can play around with the size later on. And just so we can see it, let's make it a border color of red. Okay? Yeah. So we can actually see it. Okay? But what we see is 120 squares all together. We actually need to separate them. For each one of the pixels, I want a different i, a different spark. Right. So how are we going to do it? We're going to use a sas loop. And sas loops are for people that didn't, that don't work with loops, it looks a bit scary. But once you get them, it's like, it's really, really fun. And it's really giving you a lot of power to do a lot of great things. And when you're working with 120 elements, you can, by the way, say nth child one, and then two, three, four, five. And, you know, sometimes if I have three, four elements, yeah, it's okay. But if you have 120, no, we're going to do a loop. Yeah. So a loop starts with a simple four. And you get a variable. So for i, I'm just using variable i because, you know, it's an i. And from the initial number is one, sometimes using zero, but we're going to talk about later, one through, we have 120. Okay. So if you use one through 120, so it's going to be included the 120. If you're saying two, so it's not including the 120. So the last is 119. So sometimes I'm using zero to 120. So it's the same number of repetition. But then the dollar i is equals to a different amount every time. So now it's equals to one. If I use zero, it's equal to zero. Yeah. So let's put this nth child inside of the loop. And we're going to use this dollar i, as I said here. So now it's going to loop 120 times. And every time I'm going to get a different nth child. Okay. And I'm going to give this nth child a translate. Let's say it easy. That's going to be easier because I want to translate it on a different element. And what I can do is excuse me. So I need just the value of i minus 60 pixels. Okay. Because I want to move it back 160. Yeah. Okay. So I want the center one, the first one to be minus 60 pixels and then plus one pixels for each one. So let's go and give this value here to this. I'm going to use transform because I'm going to do a lot of things to this part. So I'm going to use transform and not individual transform. So let's say translate z, var tz. And now we have, yeah. And now we have like a block. Okay. But this block, actually, if you do like a right click and inspect, you can actually see that each one of those divs. I just interrupt really quickly just in case people aren't used to seeing variables used like this, just because we're not using them as an actual value. Like here it's the nth child. And then over here it's being used for a custom property. We have to do interpolation. So that's just why we have the dollar sign and then wrapping it. The pound sign. The pound sign. Sorry. Yeah. The pound sign followed by the squiggly braces because if not, it just doesn't work. And anytime you use a SAS variable as a custom property, you have to do it there, too. Yeah. In some cases, like if I would use like in an inset, something like that, it would work theoretically. But if you put it in a custom property, you'd need to wrap it as a string. Yeah, exactly. Yeah. So now we have like this block, each one of it is in place. But so now let's move it. Let's create the animation. Okay. The animation, the animation obviously is going to be Spark. The duration is going to be duration. I'm going to add a delay, about a delay in a second. Oops. Infinite. Again, I want to move forever. And here, the timing function I'm going to use is out. Because I want to start, it's like an explosion. It's a spark. I want to start fast and move and slow. Okay. So it's is out. I'm going to use a couple of more things, but we're going to leave it for now. Let's create the keyframes. Okay. So at the beginning, I want the Spark to be very small. Okay. Like I'm going to scale zero. And then while the explosion is going to be big, that's how the scale is going to be back at one. And obviously, I'm going to move it both up and to the sides. And I'm going to move the, I'm going to switch the opacity to zero. So it's like it started one, it moves it zero. It explodes and then it dies out. Okay. So there's a few things happening in this animation. But in the beginning, obviously, the opacity needs to be one. The transform, this is the transform. And it's, this is also stays there until the laser hits this specific point, right? So it's hit, as we said in the beginning, after 25%. And then the explosion, let's say I want the explosion to be like 5%. So it's 30. So the difference is between the five and the 30, right? So we're going to move the opacity, as I said, to zero. And we're going to add, instead of the translate, going to use translate 3D. So now we have zero, zero, zero. Okay. And here we're going to give them two values. Let's say, but for now, let's say zero and minus 50 pixels. We're going to change it, but just so we can see something moves. So now, if it works, yeah. So we can see it moves. But they're all moving together. I want each of them to move as exactly as the, oh, actually, I need to move to add one more thing, scale. Before, before I'm adding the delay, let's add a scale. Here it's zero and that one. Okay. So what I need to add is, yeah, here it is. So now it's nothing. And now, yeah, so it starts at zero and then explodes outwards. Perfect. Yeah. So we can see it exactly now. Yeah. But again, I don't want it to happen all at once. I want it to happen one after the other. So what I would need to add is right here on the animation, I'm going to add delay. And the reason here, I'm not using a custom property and not assess variable, it's because it's a custom property. Each one of the element is going to get a different value of delay. I'm actually going to set this delay right here in this loop. So how much delay each one of those animations needs to get. So the total animation right now is 10 seconds, but the total movement is only six seconds. But it starts at 60 pixels before and ends 60 pixel after. So it actually touches just the panel for three seconds, right? Right. Yeah. Right. So it's actually, we can actually say it's like a duration time 0.3. Yeah. Right. So for each one of them, so it's divided by 120. Right. Because we have 120 pixels different. Yes. Yes. That makes sense. Yeah. So all we need to do now is just give them multiply each one for a dollar i and that's it. We're going to add, yeah. Okay. So we can actually see the laser. We can see something happening now, but in order to avoid this at the beginning, we need to add here in the animation, we're going to add backwards. So now before the animation starts, I'm going to have this, I'm going to have this style. Okay. So we can actually see now that the laser is like working and whenever it touches the panel, there is something happening, but it's not really nice. We need to add a little spice and the spice that I like to use is randomized. And we're going to use, you can use randomized in so many ways, but we're going to use them like in the basic way, we're going to randomize the X, like the X amount, we're going to randomize the Y and we're going to randomize the color. And maybe we're going to randomize the angle. We can do whatever we want. So in order to do it, let's have a variable, let's say you wrote a translate X. So this is like, I want to translate on the X axis. And I'm just using a random and random is a SAS function that gets some sort of value. So let's say 100 and pick 120. So now I have a random number between zero and 120. Okay. But because I want it to be like from the translate, it can be minus or plus. So I can say minus 60. So now I get like a random number from minus 60 to 60. Okay. And if I'll take this variable, and I'm going to change this, oops, I'm completely at the wrong place. I'm going to use it here, the X. So now we can see in the animation that the sparks, yeah, now it's starting looking like sparks. We obviously need to do the same thing for the TY. And you're going to replace the minus from our TY. But the TY, you can't, it has to be always negative and actually be always like a big negative, like more than 60. So let's say minus 180. So now I have a number between minus 16 and minus 180. Okay. Now I forgot to use this one. Sorry. Yeah, the final live coding. Yeah, a bit nicer. And as for the color, we really need to change the color because sparks are a bit more yellowish than reddish. So let's have a random on the hue. And the hue is the number. So we can have again, random of, oops, thank you. Let's say random of 40. So the hue will start at red. So zero, it's red. And as you go up, it goes more to the yellowish part. But if you go backwards, you go a bit more to the purplish part. So we actually, let's make it 50 and make it minus 10. So it's going to get a bit purplish to the yellow. And we need to use this hue and where we can use it right here in the background color. It's in the eye. Yeah. We can actually use an HSL. And I know HSL now it's not the best thing. It's cool. But we have all those new things. But I'm just so used to working with ASUS early in those things. And when you just, you can set the hue, it's just more comfortable. So let's see. I've been playing around with LCH. And I'm just like, my brain is so in HSL mode that this is not working for me yet. I need more practice. Yes. I'm at the same place. Yeah. It's just, you know, you used to work with it. Just like, you know, in the oldest was RGB and now it's HSL. So I added the saturation to 100% because I want it to be really saturated and the lightness to 50%. So now if you get something like this and it doesn't work because I didn't add this. Is it working? Yeah, it's kind of look better. We can add a rotation 3D or let's say like a 2D rotation. Let's edit in here. Let's have a row takes x, rx, and rotate y, ry. Okay. So actually created, I need to create those two variables. Oops. Or x. So let's do random 720 minus 360. So it's from minus 360 to plus 360, right? So it's x and y. And if we have it working, what have I missed again? And I'm sorry for this thing. I actually wrote pixels instead of degrees right here. So yeah, my mistake. My bad. But now it's working. And I actually added like a rotation, both from the x-axis and on the y-axis, just to add a bit more variation and you can actually see it now. And the sparks looks good. Anything else you want to add to these sparks, by the way? I don't know. It looks pretty good to me. Yeah. If there's something you have in mind, go for it. But I'm happy with it. Well, the thing that I have in mind is, okay, now we have a laser that is cutting, but nothing is happening. We need something that falls down to make this animation complete. And the first thing that we actually need to do is to move the panel. So the second the panel, the laser gets off the panel, we're going to move the panel aside and create a different part in its place. And that part is going to fall down. Okay. I hope it's going to make sense. It's going to make sense more once we're going to do it. So I'm going to go back to the panel class up there. And I'm going to add an animation. Again, I'm going to use here. I'm going to animate the timing function in the middle. Let's create the right window. Yeah. Okay. Let's create an animation. If you want to write, you can do it, by the way. Duration. It's going to have an infinite, obviously. And here, so at the beginning, I want the panel to move in before the laser cuts it. And then the laser is going to cut it. And then it's going to jump back to its place. But in the beginning, I want it to move slightly, so smoothly. So I'm going to add an ease in out. Okay. And I'm going to add here in the key frames, things of panel. So in the, in the zero percent, like right in the beginning, as I said, I want to be in the, like to move to the right. So because I want to move to the right, I'm going to add here a translate. Another transition. Translate of 120 pixels. Right? We said that the part that the laser is cutting the square, so 120 pixels. So we can actually see now it's move, it's in the end, but I want it to be in, let's say, in 10 percent when the laser starts moving, I want it to be at zero. Okay. So now, it moves back and now the laser starts to cut it. And now exactly when the laser leaves it at 55 percent, I want it to be back here at 50, at 120 pixels. And I want it to remain there. Okay. But again, I want the movements to be instantly. How do I make the movement instantly? I'm animating the timing function to step and so now it slides and then it's cut. Yeah. Now you can see. Nice. Yeah. Okay. So the last part is just to add something. Once you, once the panel move, I'm going to add like a different piece instead of it and I'm going to animate this piece to, to fall down. So let's add the last thing we're going to add to our HTML right here down. We're going to add a drop element. It's going to drop it. And right here in the bottom of the CSS, we're going to give the drop obviously a position absolute, position absolute, because again, we want it to be a position absolute. We're going to give it a width and a height. Yeah, let's give it a width. Actually, you know, we can actually pretty much copy most of them from, from the panel, including the, the rotate. I already copied it. Yeah. Yeah. That makes sense. Except for 120 pixels. So now, actually, if we, instead of the background, let's make it blue. So we can see it. Where is it? Yeah. There we go. Okay. This is the piece. And obviously now it's supposed to be invisible or it can just be there, but now, now it's into the animation needs to, to go. Let's leave it blue for now, just so we can see it. And we're going to add an animation. Drop. So it's going to have the same duration, obviously duration. It's going to have infinite, like them all. And I'm not sure about the time and function. Let's leave the time and function again empty for now. By the way, if you don't put any time in function, the default is and I, I normally don't, don't leave them empty. I leave them empty for now. Keyframes, keyframes. Kotlin really need to add keyframes to them. Yes. Keyframes. So in the beginning, at 0%, I want it to be very, very down in the bottom. So let's do another translate again, but I'm transiting the Z axis. I want to be on the bottom. So it's 0x, 0y. We can actually play around with the x and y if we want to move it while it drops. But for now, let's say minus 100 VH. Okay. So now it's all the way oops. Why is it? Oh, actually I need the y. Excuse me. I need the y. Okay. So why do I need the y and not the z? Because I'm using individual transform and when using individual transform, the translate happens before the rotate. So I'm first translating on the y axis and then rotating. If I would use regular transform, I could set my own order. But in individual transform, the translate happens before the rotate. So yeah, you actually need to move it on the y axis and then you need to move it down. So 100 VH. So now it's in the bottom and it moves up. But I need it. I want actually to be like at step end because I want to stay there and I want it to come back to place instantly at 55%. 55% is where the laser leaves the panel. So if I put this on 0, so now it's somewhere in the bottom and the second it moves, it jumps back to place. Okay. And what we need now is just to animate it back to 100% back here. But obviously we don't want it to be step end. So the last thing we're going to add, so you won't forget it. You can animate the timing function. It should stick now. Yeah. And we're going to use ease in because I wanted to start you to fall slow. And if I haven't forget anything, so now we can see the cut. We can see the panel here. We need to change it to white. Yep. And it's supposed to be pretty seamless. Yeah. Yeah, that looks pretty good. And then the next one moves in. Nice. That's really cool. And this is how you do particle animation since CSS. That's awesome. Yeah. Yeah. And I will say one for me, one of the things that really I liked there too, because whenever I have like multiple things that I'm trying to animate that are sort of should be linked together. But the timing like really like the timing of the drop, let's say is a little bit different because it's only at that 55% really, but like I would just make the animation of the drop and then try and figure out the delay to get the timing of it to be proper here, not having to do that and just having everything on the same sort of scale, but just choosing okay, it needs to happen at this percent of the main animation makes so much more sense. Because you like, you need to like imagine a timeline just like in a video editing software if you ever work with one. And it's like it's different channels of things starting and ending in different the time, but the duration, the total duration is still the same. Obviously, if you're working with animation that have different duration, because sometimes you need to set the duration differently. And then syncing is a whole different problem. Yeah. Yeah. Yeah. That's it, I think. I hope you like it. I hope you learn a few nice new things. Working with random is really nice. There's so many things more that you can do with random, not just the angle and the color. Everything starting from the size, where it's hitting, like the weight of so we can actually like move things back down like the fireworks. And there's a lot of things that you can add just by using random and obviously when you're using that many numbers of elements, you just make things easier. That was amazing. And I just want to say a very big thank you to Amit for showing us how we can do that. If you'd like to see more of the crazy stuff he does, there is a link to his code pen that's just full of mind blowing amazing things. And his Twitter account is there as well if you want to follow along with the new stuff that he's constantly creating. But maybe you really enjoyed this video and you want to learn how to do more 3d CSS amazing things. And this isn't the first time Amit has joined me. He has in the past where we looked at creating a spinning 3d cube with a ball bouncing on top of it. And if you'd like to see that the video for it is right here for your viewing pleasure. And with that, I would like to thank my neighbors of awesome TTLLD, Bailey, Andrew James, Enrico, Michael, 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 court on the internet just a little bit more awesome.