Making a Responsive and Interactive Animation with SVGs in CSS
Setting up Our Animation Project -
Making SVGs Ready for CSS -
In this lesson we'll learn how to create SVGs using Adobe Illustrator and optimize them for CSS animations. Let's go into our project folder and in my underwater fun I've also created one called Illustrator Files and this is where I'll be putting all my original files ready to be exported into SVGs. I'm going to open up Adobe Illustrator, Command + N or Ctrl + N if you're on a PC and as a size I've chosen 1024 x 768 and portrait orientation. The reason I'm using this is because it's got an aspect ratio of 4 x 3 and that's about the aspect ratio most commonly used in tablets and smartphones. Now some of them are a little bit wider than that, but that's not really a problem since we're going to make our background repeatable and everything will be scalable anyway. So we could use something smaller or bigger, as long as you have a similar aspect ratio. Go ahead and hit OK. And this is going to give us an artboard of that size and in our layers palette is where we'll be putting all of our SVGs, one on top of the other, separated in layers. Now I went ahead and created one before. Go in Illustrator Files. I made an underwater scene and as you can see, it's got a background color, some waves, a bottom submarine, and the fish. The submarine itself is also separated into sub layers for every element that has to be animated. So there's a propeller that will turn. There's a periscope that will go up and down and there's the body. And the fish, the sub, the bottom, the waves will all be separate SVGs. Now a little note about the waves and the bottom. These elements will have to be repeatable in some way, by which I mean if I select one of these waves for example, I'm going to move this one to the left a little bit. If I make a copy, Command + C, Command + F, and I move them next to each other, you'll see I've made the waves so that the end of one wave aligns perfectly with the start of the next one so every wave element and the same for the bottom is actually a repeatable pattern. So you're going to need to do that in order for the application itself to have a background that can stretch or repeat in the direction to the left and the direction to the right in case you're displaying your application on a screen that's a little bit wider than the 4 x 3 aspect ratio. So keep that in mind when you're creating a background. Now I'm going to into my files. So what I need to do now because I've separated all my SVGs into layers, I want them to be exported into separate SVGs as well, of course, but Illustrator doesn't really allow you to export layers into separate SVG files. So I'm going to go and duplicate this scene four times. That's Command + D four times and I'm going to rename that to the name of every SVG that I want so I'm going to have a submarine. I'm going to have fish and I'm going to have the bottom and waves. Now if I go to submarine and I open that one up for example, I'm going to need to delete every layer that's not a part of this submarine, hit the trashcan and now I've got just my submarine and I'm going to resize my art boards to match this size. So make sure it's maybe a little bit bigger, but certainly not smaller than your elements. It doesn't have to be precise, it just has to fit your SVG into it. So hit Command + S. If you go back, you see the preview is just our submarine and you do that for every separate file except for our scene of course, that's the master file. We leave that one the way it is. And now we need to export those files into an SVG and we're going to go to save as or save a copy and into Illustrator files, I'm first going to make a new folder at the bottom left. You see this new folder button, underscore export is what I'm going to name it and as a format I'm going to choose SVG. Hit save and there's an SVG button at the bottom. The SVG profile, just leave it at 1.1, click that button and you can see it's going to make a text file and open it up and I think in text edit automatically and this is your code for your SVG with a strange name on top, what you can just rename that to, let's say submarine. And the location you can change that one to export. That's the latest folder. You add it, and if you go to the finder, you're going to find that file right there. So I've deleted the extension and I'm going to replace the extension with SVG and it's going to give you a warning. Choose use.svg and this should be your file. You do that for every separate one and you should have a whole list of them right here. Now as a rule, this should be enough for your HTML file to handle, but we want to optimize this SVG a bit. So what I'm going to do is I'm going to go into Chrome and load an SVG optimizer and choose my file, hit enter, upload that file. Oh, I see my link has expired and I'm going to go back and refresh this SVG optimizer again. Hit choose file, submarine SVG upload this again. And now it should work. Yes, here it is. I'm getting a couple of options. My decimal places will need to be 2, for example. That's just the size of our art board is going to round this number a bit. I'm going to convert the styles into CSS. That's the only thing I need to check. Hit optimize file. Download link and in my downloads folder there should be one strangely named file and this is the one. Now this optimize file is what I'm going to be putting into my web application so we'll go to the web and then SVG and drop that one in here. As you can see, I already made one before, but I'm going to delete that one for now. So I've got my strangely named file. I'm going to rename that submarine again and I'm going to add opt for optimized and I'll go into my code editor and as you can see, all the styles have been separated and all the colors and background colors and things like that have been put in the top of my file. Now I'm going to need to change a couple of last things. For one thing, I need to add preserve aspect ratio to the top and that's going to be xMinYMin and meet and a width of 100% as well as a height of 100%. And this will make sure that everything is scalable at a certain, at the proper aspect ratio. One last thing I need to do is I'm going to need to change all the IDs inside this file and replace them by classes. The reason I'm doing this is because if I'm going to need multiple versions of an SVG, for example, multiple fish, I can't have duplicate IDs in the code so I need to change this to classes. I think Command + option F will be find and replace. ID by class, replace all, Command + S to save this and that should be it. So if you do the same for every separate SVG, save them in your web SVG folder, and that way you should have all your files optimized and this is how we optimize our SVGs for use with CSS animations.
Introducing Sass for Better CSS Writing -
Setting up the Scene and Importing Our Graphics into HTML -
Building the Scene by Placing and Scaling the SVGs -
In this lesson we will learn how to position and place the SVGs to build our scene. In the last lesson we saw how we can inject the SVGs right into our HTML. Now the next thing we need to do is scale and position all the elements according to our design. So the way we're going to do that is by first go into our SVG styling block and we're going to add a few general styles so for the SVG I'm going to put a display of block because we need that to make dimensions. Position of absolute, and that's the way we're going to position everything relative to our scene, and then an overflow hidden because we don't want any element to extend outside of the bounding box of the SVG in case there are any loose elements that would extend otherwise. So that's the basis. In my layout I'm going to add all the classes for the elements so the waves first, then on top of that we're going to have our bottom SVG so all the plants and everything. Then we're going to have our submarine and then we're going to have the fish. So everything is positioned in layers sort of on top of each other. As you can see in the Illustrator file, the waves are behind the submarine and the plants are on top these waves so everything will get a zed index. The waves are at the lowest so it's at the index of 0. The bottom on top of that is a 1. Submarine is getting a 2 and then the fish will get a 3 and because they will swim right across the submarine in our end result when we actually make it swim and make everything move. So this is the basis. Then for the dimensions, the waves of course are the full size of our scene so 100% for the width and the height. The bottom itself, those plants, will have a width of 100% and the height will be a special thing that will be calculated based on the pixel size and there's a calculation we'll be using for the submarine and the fish as well, but first before we do that, we need some reference numbers. I'm going to put those in variables and my helpers. I'm going to save my size, my height, and the width of my scene basically, of my art board. So a variable starts with a dollar sign. I'm going to set a scene width of, let's see that's 1024 that I used and then a scene height and that's going to be 768, so that's our basis for our calculations back to the layout. For the height of the bottom element, I'm going to go into the code of my bottom SVG and I've got a view box property here, which has my coordinates and my size so 1024 is the width in pixels, 135 is the height in pixels and that's the number I need. Back in the layout I'm going to put this right between these brackets, 135, divide this, so that's the pixel height of my SVG divided by the scene height. Scene height and then multiply this by 100 and that number will give me a percentage. Now I'm going to add the percent sign after this because if I don't, I will just get a number without a unit and I need the percent unit for this. So this is for the bottom. I'm going to do the same for the submarine and for the fish of course I will change this pixel value, but the similar calculation for the submarine itself and this is a width and scene width of course. Copy that and put this in here. For my submarine I've got 517 and 417.3. For my fish, 131 and 88. So back to my layout and if I remember correctly, so 517 for the submarine and then a 417.3 for the height. The fish was 131 and the height was 88; s those should be our dimensions. If I go back into Chrome and I refresh, everything should be scaled and absolutely positioned. So now the next thing I need to do is set my coordinates. So the waves are already right. Those are to the top and to the left, but I'm going to set them explicitly just to be sure. The top and the left of 0. That's for the waves, actually. And for the bottom, that's almost the same. The bottom is going to be a bottom of 0 instead of a top. Now in the submarine we'll have a left of 0 because it's set all the way to the left and the height is I think about a fifth or a fourth maybe so let's say maybe 24%. It doesn't have to be exactly the same thing. Just somewhere, yes, close to it. And then for the fish, a left of maybe 70% and I think if I go in Illustrator it's a little bit below the top so the top of 50%. So I'm just making some guess work. It's just some eyeballing. It doesn't have to be really, really pixel precise because these elements will be moving anyway so I just need a starting point that's somewhere in the middle. So that's about it, I think. So yes, it looks about the same. Now if I start scaling this, you'll notice that my scene is actually aligned to the top, which means that my background color on my body tag, this blue is actually extending behind my bottom or basically behind the ocean bottom that I created. So I'm going to make a little tweak to these colors. So when I'm in this media query, so smaller than my four-thirds ratio, I'm actually going to change the background color. So the body background color will have this green so that way everything behind the scene will extend into this color and then the scene itself will be this ocean blue. So I'm going to go into my scene. Yes, the background color and this background color is this blue that I put on the body tag earlier. So this is inside this media query that I made in the previous lesson. Now for my body tag I'm going to add a background color as well, but this one is going to be green. So in Illustrator I'm selecting my bottom elements, double clicking the color on the left, and copying that value, paste it in here. Save, go back to Chrome, and it's extending. Now you might notice there's a little white line right here at the bottom, just at the place at the divider between, actually the scene and the rest of the body. So the reason for that is because we're actually using percentages for scaling and positioning and things like that and that means when we're resizing the window, everything is getting recalculated by the browser and aligned on a pixel. So if a percentage falls between two pixels, the browser is going to round this to the nearest pixel and that means sometimes we're going to get a pixel line and one way of countering that is by moving the bottom a little bit down so it overlaps with this background color. So I'm going to give that bottom a -1 pixel and that should fix things. Yes, no more line right there. So if I scale this, if it's longer, it's aligned with the bottom and if it's like this, it's actually the bottom color that's extended right there. And so yes, this is a look at how we position and place the SVGs to build our scene.
Animating Our Background -
Animating the Submarine -
In this lesson we will learn how to combine animations in order to make a submarine move. So now that we've got our moving background, we'll also want to manipulate the foreground. I want this submarine to go up and down slightly following the waves and I want this propeller to rotate so that it gives the illusion of giving the submarine movement. So I'm going to back into my code and I'm going to add another keyframe animation so I can just copy paste the setup and give it another name. I'm going to move this bob because it's bobbing up and down. I'm going to change the coordinates so instead of an x coordinate, it's going to be the y coordinate, so the second one and I'm going to need five of these and why? Because I'm actually going to make this move in two directions and back to the center so it's going to start at the center and then it's going to go 25%, to 50, 75%, and 100. So percentage is just a division of the number of keyframes that we need. So from 0 to -5 position, then back to 0, then to +5, then back to 0. This is going to give us a sign wave and it's going to go like this, up and down and up and down and infinitely repeated. So in our animations SASS file I'm going to add the same thing as I did for the background so submarine and then vendorize our animation and call our bobbing animation and the timing is going to be 4 seconds which is a bit faster than the background itself and I'm going to refresh this. That looks about right. So timing is something you're going to have to tweak. You're going to have to feel it out a little bit. So I've done this a couple of times before so I've got a pretty good idea of how fast or how slow I want this to go. And now that I've got this element, I've also got to take care of a small bug for Explorer and that is if you start a keyframe at a certain position, that is 0 for example, I make it end at the same position, you'll sometimes get a glitch. So in order to avoid getting a glitch, I'm actually going to add a few decimal points to the 0. So it's a number small enough that you won't notice any animation, that it's not the original starting position, but it makes it different from 0, which makes Explorer actually use that keyframe instead of ignoring it. So that should be it and the other thing I want is to make this element rotate the propeller and for that reason we're going to make another keyframe animation so I'm copying my setup. I'm going to call this spin and it's going to be rotate instead of transform from 0 degrees. So your unit this time is in degrees, to 360, which is a complete revolvement and from 0 to 100 so only 2 keyframes and in my submarine I'm going to nest this. My propeller is actually a group inside my SVG. If you'll recall, we made our submarine, we split it into sub layers. If you go back to Illustrator, open your palette, you've got three sub layers and those will be named groups as well inside the SVG. If I go inside the SVG, when we export it, they were IDs and we renamed them to classes. So this is the thing. Now we would expect that this would just rotate in a normal way. Unfortunately we're going to have some issues with that as I'm going to show you. So if I add my propeller, vendorize animation, then we'll call it spin, and a bit faster than submarine movement so 2 seconds and again infinite. As you can see, it's rotating very strangely. It's actually taking the top left corner as a coordinate. Now we've got two solutions to fix this. Either we give it a coordinate using transform origin in the CSS, unfortunately that doesn't work in Firefox. That just ignores coordinates. It will always take the top left. So that leaves us with one other solution and that's actually hard coding the coordinates right into our SVG. Unfortunately, in order to do that, we have to change this layout slightly. So these stacks. So instead of having a group called propeller, we're actually going to have to nest two SVGs with the coordinates of our propeller and it's a bit weird and a bit counterintuitive to do it this way, but it's the best solution I've found to fix this. So I'm going to indent this a couple of times and I'm going to quickly copy paste this from my notes so you can quickly see what's going to change. So instead of this one group we've got this, an SVG, a group, SVG, and another group. So I'm going to undo this for a moment and add a little more indentation. So this becomes very clear. So instead of this group class propeller, I've added an SVG around it and I've moved the class right to this and then we've got a group and then another SVG and then another group. So one group was replaced by two groups and two SVGs. I'm going to close that at the bottom so I don't forget to do this so I don't get any mistakes. Let's see. This should be right here and this should be right here and save. The first SVG has my as positive coordinates as you will see, and the second SVG will have the same coordinates, but negative. Again, it looks very illogical, but it's actually a way of pushing down the propeller and then pulling it back up and by doing so, you're actually moving the center point or the top left point to the center and to know the coordinates of your element, you can actually go inside your layers of your element, your complete submarine and you just click your propeller that's nested, open your transform panel right here and look for the middle coordinates, the x and the y, and that's the numbers you want to use. So that's 78 something and 257 something. Going back here, positive on the first and negative on the second one. And then what we're going to do instead of, of course, rotating this propeller, what we're going to do is we'll target the propeller group or better yet the propeller SVG and then the first group that's in there. So that's propeller and then the bigger than sign and then the g, that's targeting the first group inside our nested SVG and this is where we give the spin to. I'm going to go back and refresh. As you can see, it's rotating, but as piece is cut off and that's because I set overflow hidden before on SVG so I'm going to make an exception. Inside my submarine I'm going to add an ampersand. That means repetition of the submarine class. Add SVG after that and give that an overflow visible. Go back, refresh, and that should rotate it. Now one last remark on this. This will now work in most modern browsers including this rotation, except for Explorer 10 and 11, I believe. They have problems with manipulating or animating nested groups and nested SVGs inside another SVG. There is not really a pure CSS solution to do that, to fix that. So if you want an animation like this, if you really need this to work in Explorer, you're going to have to pull the propeller out and make it its own SVG so like we have the fish and the submarine and the bottom and the background, you will need to make this its own file and export this as an SVG from Illustrator, optimize that, follow all the rules with it for the separate SVGs and then you can position and animate it. Now I'm not going to do this because this animation in my eyes is not really essential to the animation as a whole. The most important things I think is that the ocean moves, that the submarine moves a bit and later we'll have the fish move as well. So this propeller is a nice extra, but again, if you want to make this move, you could do that by separating the SVG. Another element we still have is this periscope right here. If you want to make this one move, for example, you could do that as well. One thing you could do for example is write a keyframe animation to move this along the y axis to move this up and down again and for example, trigger it on the submarine hover. That's something I'm going to let you decide if you want to do this. We've seen how we can build animations and keyframes so that's something you could test out if you want to. So this is how we combine animations to make our submarine move.
Making a School of Fish -
Interacting with the Fish -
Turning Our Animation into a Touch-based Game -
Dealing with Partial and Nonexistent Browser Support -