Styling and Animating Scalable Vector Graphics with CSS
Sara Soueidan, CSSConf EU 29:16
transcript
Um, welcome to styling and animating scalable vector graphics with CSS. Um, quick introduction, my name is Sara Soueidan. I'm a freelance front-end developer from Lebanon and a writer. I'm also an author on team up at Codrops. Um, like Jed said, most of my work and writings have been about CSS and SVG lately. And you some of you may know me through my writing, some of you may not. So, yeah, that's just it pretty much. Yeah, so I love SVG and for a very good reason. SVG is now like the new hot thing in web design today and for a good reason. Uh, I'd like to kick this talk off by quoting Dmitry Baranovskiy. For those of you who don't know who Dmitry is, he's the guy who created uh, the Raphael SVG library and more recently the Snap SVG library. Um, Raf, um, not Raphael, Dmitry gave a talk a while back called you don't know SVG. In his talk, Dmitry said, "If you don't know SVG, you can't call yourself a web developer. Call yourself a web enthusiast." Yeah, now I'm not saying this to make anyone who doesn't know SVG feel bad. I'm just saying this to emphasize the fact that SVG is becoming a real vital and important part as in our work as web designers and developers today. And so we have every reason to start learning it and working with it and introducing it into our workflows. But, when I first started learning SVG, I had certain expectations. Um, I expected SVG to work and behave like HTML in many aspects. Be it styling or animating or I even expected there to be a content flow, but turns out there isn't. There is no content flow in SVG and every everything is basically just absolutely positioned and inside a inside a canvas. And you know, there were there are a lot of things like we have six ways to embed an SVG on a web page and I was like, "Okay, so I have an SVG, but which way which which embedding techniques should should I choose? There's a lot of confusing things for someone who hasn't worked with SVG before. So, I'm hoping that by the end of the talk, I will have saved a lot of you, maybe hopefully, some frustration when you're going to work with SVG. So, um I'm going to be talking about creating, exporting, and optimizing SVGs, styling them with CSS, then animating them using CSS animations, then the different techniques for embedding SVGs, pros and cons of each, then making SVGs fluid with CSS. There are certain hacks and fixes that you have to use to make it work. Uh then using CSS media queries. If we're talking about responsive design, we have to mention media queries, how to make SVGs adaptive, and just a little bit more in the end. So, creating, exporting, and optimizing SVGs. Um there are a lot of SVG editors out there. Uh the three most popular ones are Adobe Illustrator, Inkscape, which is a pretty decent alternative, uh and there's Sketch, which is not free, but it's also Mac OS X only. Now, no matter which editor you choose, none of them outputs perfectly clean and optimized code. Most SVG exported usually contains like editor metadata, uh comments, um non-optimal decimal values, and empty groups and elements, and a lot of stuff that you can remove from your SVG safely without affecting the rendering result. And of course, you would have cleaner code to work with. So, it's generally a good idea to use a stand-alone tool after exporting your SVG to optimize the code and make it ready to work with. Now, there are several tools for optimizing SVGs. I'm going to be talking about two. Uh the first one is Peter Collingridge's SVG editor. This is an online tool. It allows you to input uh some SVG code or upload an SVG file, and as you can see in the screenshot on the left, uh you get to see a live preview of of that you entered, and on the right you have a set of options a set of options that you can choose to to apply to the SVG. Like you can you can apply optimizations such as remove removing white space which it makes the code compact and reduces file size removing empty elements, unnecessary groups, combining paths where possible. This tool is my favorite. It's the one that I recommend and that I use simply because of the fact that you get to see the result of applying a certain optimization. Now, why is this important? Because sometimes certain optimizations that you apply may end up breaking your SVG like completely breaking it. If you have animations, they may be broken. If If you even if you don't have animations, the SVG would look like broken. It It won't work anymore. So, on the right I have an example showing an SVG which is a very simple path that I exported from Illustrator. You can see at the size of that code and then after optimizing it with Peter's tool, this is the result that I got at the end. It's very small, compact, and very readable. The other tool, if you don't want to use an online tool, you can use the SVGO which stands for SVG Optimizer. This is a Node.js based tool which also allows you to apply a lot of optimizations, but these are automated. You don't get to choose the optimizations. I've used this tool. It broke my SVGs. I've heard a lot of other developers say the same. It's not the tool's fault, but not being able to choose the optimizations, like I said, may end up breaking your SVG. But if you want, you can use it and it comes with a nice drag and drop GUI as well. So, after you've exported your SVGs, made it ready to work with, you can now apply styles. Okay, so the dividing line between HTML and CSS is clear. HTML cares for the content and structure, and CSS cares for the looks. However, in SVG, that line is blurred to say the least. In SVG, we have something known as presentation attributes. In SVG 1.1, we did SVG 1.1 did not require any CSS. So, the styles were applied to the SVG using presentation attributes. This The example shows like we have the width, the height, basically the code in blue. The fill, stroke, and stroke width are all presentation attributes. A subset of all SVG presentation attributes can be set via CSS using as CSS properties. And some of these SVG attributes that you can set via CSS, some of them are shared with CSS. They are already available as CSS properties, and some of them are not. The table shows like some of the ones that share are shared with CSS like font, font family, visibility, clip path, etc. And others are SVG only. Now, there are now a few or more like a lot of SVG attributes that we cannot set using CSS. Like we cannot change the width, the height, or the position X Y or CX CY. We cannot set them in CSS right now. But, in SVG 2, more attributes will be added to the list, and we will be able to specify the width and the height and positions of SVG elements using CSS properties. Okay, so in addition to Okay, just one more note about presentation attributes. They are sort of a special way of setting a CSS property on an SVG element. You can think of them as special style properties. And so, they they do contribute to the style cascade. But, we'll talk about that more at the end of this section. Okay, so styles can also be applied Okay, so because we said that some presentation attributes can be set as CSS properties, these CSS properties can be set inside a style attribute in line, just like we can do with HTML. We can set them inside a style tag. The style tag can be inside the SVG. You just select the element that you want to style like the polygon in this case, and set the properties that you want, the fill, stroke, stroke width, etc. You can also specify the styles in a style tag outside the SVG if you're embedding the SVG in line in an HTML document. Note that the SVG here does not have an XML namespace attribute. You don't need that if you're embedding it in an HTML5 document. Notice the doctype at the top. It's an HTML5 document. And last but not least, if you want to completely separate your styles from your from your structure and you know, from the SVG, you can include the the styles uh you can reference an external CSS stylesheet using the XML stylesheet element inside the SVG file. Okay. So, style cascades. Uh presentation attributes, they do contribute to the style. Now, if you SVG element, for example, I have a very simple circle here, and you apply some styles to it using presentation attributes, inline styles, external styles, document styles in this case, and there's also one I have a group, a G group, and I have applied a full color, a yellow full color to the group. Now, one thing about the group in SVG is that if you apply a style to the group, it's going to be inherited by all the all of the elements inside that group. So, we have a circle. The circle has uh styles applied using presentation attributes, inline styles, inherited styles, and document styles. So, which one of these wins? In this case, the one that wins was the deep pink at the deep pink. The circle is pink. The uh So, the figure. Okay. The figure on the on the right on the right shows uh the order of the of this different styles and and the cascade. So, you can see that presentation attributes count as low-level author stylesheets, and they are only overridden they they are overridden by all of the other style uh style declarations, be them external, document, or inline. The only thing that presentation attributes will override is user user agent stylesheets, the default stylesheets applied applied by the browser, and inherited styles. So, in this case, if we if we remove all of the styles and only keep the presentation attribute and the inherited style, the presentation attribute is going to override the inherited style. But, all of the other CSS declarations are are to override them. I wanted to emphasize this because I've had a lot of questions about this like some people applied uh styles for an element and it was inherited but they didn't know how how they would override it. So, I just wanted to emphasize this point here. Uh in the diagram styles lower in the diagram override those above them. So, animating SVGs with CSS. Um now, because we can style SVGs with CSS, we can also apply animations using CSS transitions and animations and keyframes. A very simple example could be done done just by adding a very simple transition. For example, we have an icon from the iconic uh icon set here. We have a lamp. What we're doing here is just that the once you hover over the lamp, uh I've also over highlighted the styles over here. You just apply the styles and hover and hover styles normal just like you would with HTML. Once you hover over the the lamp, the stroke color changes, the stroke width changes, and we're adding a very slight background by adding a radial uh gradient at the back. So, this is a very simple animation that you can add using CSS transitions. However, most animations are more likely going to contain some kind of transformations. And in most aspects, SVGs respond to the transform and transform origin properties in CSS in the same way like HTML. But, there is one one difference that uh you need to be aware of. The transform origin in SVG versus HTML. An SVG element does not have a box model. It does not know what a what a border box is or padding box or a content box. So, in in HTML, if you have an element no matter what it is as what it is, the the default transform origin is 50% by 50%. This is a default value, which is the center of the element itself calculated relative to its box model. But, in SVG, the center of rotation is 0 0, which is the top left corner of the SVG canvas, not the element itself. So, say for example, you have a div and a rectangle. A div in HTML and a rectangle in SVG. I have applied both same styles to both of them. And then I rotated them using CSS the CSS transform property by 45°. The one on the left, which is the HTML element, is rotated around its center. But the one on the right, you can see that the SVG canvas, which is the light gray, the element is rotated around the the top left corner of the SVG canvas. Now, in most cases, this is not what you would want. So, you will have to change the the value of the transform origin on the SVG element. You can set it using either percentage values or absolute values. If you set it using a percentage value, the percentage value is going to be calculated relative to the element's bounding box, which includes the stroke used to draw its border. And if you use absolute values, the the value is going to be set relative to the SVG canvas. So, for example, if you go back to the previous example and I want to set the transform origin of the SVG element to 50% by 50%, this is the result that we should obtain. Okay, and this works. It works on Chrome, but there is a bug in Firefox. It has been around for a for a really long time. I don't know why. I hope it gets fixed soon. Setting the transform origin in percentages does not work in Firefox. So, you're going to have to use absolute values to make it to make the animation, especially the rotation, work. If you're not doing any rotations, the transform origin is not going to be a problem to you. You don't have to change it. But for rotations, you will have to do it. Okay, so uh this is an iframe. Okay. Um Could you just give me a few seconds? I'm still in the editor mode here. I didn't notice that. Mm. Where is the presentation mode? Great, I'm completely lost now. Um slides are I'm just going to use the local version. Sorry for this. Just Okay, so here's the iframe. So, I have a very simple example here rotating a pinwheel. I wanted to rotate it around its center, so I've used both percentage values and absolute values to make it work in both Chrome and Firefox. And then using CSS animations, the animation property and keyframes, I've just applied a a rotation that it just keeps rotating infinitely. Okay? Uh what about 3D transforms? Well, they work. You can transform SVG elements in 3D, but um there are bugs. First of all, perspective the perspective currently doesn't work in Chrome. That is probably a bug or maybe it is just not implemented yet. And another thing to note here is that we did 3D transforms on SVG elements are currently not hardware accelerated in Chrome. They have the same performance profile as SVG transform attributes. They are hardware accelerated when they are applied to HTML elements, but they're not when they're applied to to SVG. Now, CSS transitions and animations can be used to animate any of the properties shared with CSS, but not the others. Like we mentioned that that some of the presentation attributes can be set with CSS and some of them cannot. So, one of the examples that cannot be achieved with CSS is animating SVG paths by morphing paths from one shape to another. This is one of the most powerful features about SVG, which is SVG paths, and more the most impressive effects can be can be created by animating paths. But, this is currently not possible in CSS. In order to animate a path from one shape to another, you would have to animate the D attribute, which specifies the points that make up the path. We cannot do that in CSS now. So, if you want to do that, I recommend recommend using the Snap SVG library, which is uh described as being jQuery for SVG, the jQuery of SVG. Another thing that we can do in SVG that we cannot do in uh that we cannot do in H No, that we cannot do using CSS animations is moving an element along a path. Using CSS Using SVG, we can use the animate motion element. It's part of the smell specification and introduced into SVG. We can move an element along a path. It can be any element. I just used this as a very simple example. We cannot do that in CSS yet because uh Dirk Schulze from Adobe uh he proposed to the CSS working group to add uh animation along a motion path in CSS. I do hope this sees the light. He proposed it like maybe a couple of weeks ago and it looks very solid. I hope it makes it to implementation. Okay, so embedding SVGs. There are six ways to embed an SVG on a web page, but why are we talking about embed- embedding SVGs in the talk about styling and animating SVGs with CSS? Well, it's because The reason is because um the way you embed your SVG is going to determine whether or not the styles and animations you apply are going to actually work or not. Because sometimes if you embed your SVG using a certain technique, uh interactions are not going to work or animations may not work. So, the six techniques are First, we can embed the SVG using an image tag, just like you would any other image. In this case, CSS animations will still work only if they are specified inside the SVG tag. If you link to an external style sheet and that external style sheet contains CSS animations, they're not going to be preserved. They have to be specified inside the SVG. CSS interactions, like if you have an hover a hover effect, they're not going to be preserved. They're not going to work. The same applies for an SVG embedded as a CSS background image. CSS animations will work if they are included inside the SVG. Interactions, hover interactions, CSS interactions are not going to be preserved. The object tag can also be used to embed an SVG. Now, the advantage of the object tag is that any scripting that you use is going to work, but we're not going to We're not focusing on JS now, so I'm going to skip that. It also comes with a default way for providing fallback for browsers that will not be able to render the SVG. Between the opening and closing tag of the object, you can provide any fallback, be it text or a PNG fallback or whatever you want. And the case of the object tag, CSS animations and interactions will work if they are specified in inside the SVG. The same applies for the embed tag, only if they are inside the SVG. The iframe also pro comes with a default fallback mechanism. Also, SVG animations and interactions will work only if they are specified inside. And last but not least, an SVG embedded in inline in in in an HTML document. has a lot of advantages, but you will not There is no way There is no default way to provide fallback like there is with the other techniques. Uh however, CSS animations and interactions will work even if they are specified outside the SVG. This is uh one of the main advantages of inline SVG. Okay, so after you've embedded your SVGs, you're going to want to make them fluid. Now, um there are certain hacks and fixes that we're going to have to cover here because the first thing you you need to do when you want to make an SVG responsive is to remove the width and height attributes. That's the first logical thing. Any element that has entry specific if you if you explicitly set the width and the height, it's going to maintain those dimensions. It's not going to be fluid anymore. So, the first thing you do is to remove the width and the height. The second thing you do is please make sure you keep the view box. SVGs exported from graphics editors usually contain a view box. Keep it. Without the view box, the SVG will not be responsive. Even if you apply the fixes and hacks, it's not going to work. Keep the view box. The third thing is you may not you may not have to do this is to set the preserve aspect ratio to xMidYMidMeet. What this value does basically is that it makes sure that the browser makes sure that the SVG content is scaled as much as possible while remaining inside viewable inside the viewport of the SVG and preserving its aspect ratio. It's not going to be distorted. So, the reason I said this you may not need this is because that this value is the default value. So, if the SVG does not have a preserve aspect ratio set, you don't have to explicitly set it. It's just going to default to this value. Now, you can, of course, change the view box and preserve aspect ratio values if you know how to use them to to control the SVG if you want to change that, but generally, if you don't want to if you don't if you just had the SVG and you want to make it fluid, just keep them the way it is. Also, note that preserve aspect ratio has no effect if the view box is not set because preserve aspect ratio is mainly used to scale and position the view box inside the SVG viewport. Okay, now you embed it. Removing height and width, keep the view box embed. Now, we're going to have to apply fixes where and when needed because browsers, after removing the width and the height from the SVG, some browsers are smart enough to determine the dimensions of the SVG, and some of them are not. Um you can imagine what browser is not really that smart, right? Yeah, so we're going to go over each technique and then mention the fix or the hack needed to make the SVG fluid. The first one is if you're embedding the SVG as a background image in CSS, luckily, you don't need to add any fixes or hacks. It's going to be responsive. It's going to It's going to behave just like any image that you use as as a background image in CSS. If you're embedding the image the SVG image using an image tag, you're going to have to explicitly set the width to 100%. This is required for Internet Explorer. Duh. Because um well, the default dimensions for non-replaced elements in CSS is 300 pixels by 150 pixels. Now, Chrome and Firefox and, surprisingly, uh Internet Explorer are smart enough to know that the width of the SVG is going to be fluid. Okay, so if you have the SVG inside a container and you resize the container, the SVG's going the SVG width is going to resize with that container. But, in Internet Explorer, it keeps the the height at at at at 150 pixels. I don't know why. So, you need to explicitly set the width to 100% so that so that Internet Explorer can start, you know, scaling the SVG as it as it should. Um if you're using an object tag for the same reason, Internet Explorer, you're going to have to explicitly set the width to 100% to make the SVG fluid. Now, using an image tag or an object tag in Chrome and Firefox, the SVG is fluid. As soon as you remove the width and the height, it's going to behave as it should be and it should be fluid. But again, in Internet Explorer, the height is going to be fixed at 150 pixels causing a lot of white space on to on the the right and the left of the SVG. So, you need to explicitly set the width to 100% to make it work. Again, the same for the embed tag. For Internet Explorer, set the width to 100%. Now, when you're using an iframe, we're going to have to use the padding hack. Okay, so again, I'm going to ask um how many of you are familiar with the padding hack? Okay, that's surprising. Okay, so iframes. I'm pretty sure that most of you has have used iframes sometime to embed in a video or another webpage or whatever. Iframes are by default not responsive. And when you're embedding an SVG using an iframe, it defaults to the size that is the default size of the non-replaced elements in SVG, which is 300 pixels by 150 pixels in all browsers including Chrome and Chrome and Firefox. So, in order to make the iframe responsive, we're going to use the padding hack with the famous padding hack, which is which was basically introduced in in an A List Apart article as as an as a hack to make iframes responsive. Now, the way the padding hack works is there are certain steps. After you've removed the width and the height of the SVG and embedded it, wrap the SVG in a container, which means you wrap the iframe inside a container. No matter what the container is, we're going to use a div because it has no actual actual, you know, role. It's just a container. We're going to collapse the container's height. This is how the padding hack works. You collapse the container's height by setting the height to zero, and then apply top or bottom padding such that the resulting height or width ratio equals the SVG's height to width ratio. Now, why why are we applying top or bottom bottom padding? The reason for that is that when you're applying a bottom padding, let's talk about top padding in this case. If you If you're applying a top padding to an SVG to an HTML element, if you're using percentage values, the percentage is going to be calculated relative to the element's width, not relative to the element's height. Okay? So, when you apply a padding like uh padding top 50%, the padding is going to be equal to 50% of the width of the element. So, I'm going to go over this technique again with the code in a second. After you've applied the padding hack, you create a positioning context inside the container, then position the SVG absolutely inside the container, and give the SVG height and width. This is pretty useful uh useless if I don't go over it again, right? So, the container on the right. Uh first, we have wrapped it inside a container on the left, and then we've collapsed the height, applied a width. The width of the container can be anything. It's It depends on where you want to embed it on a on the page. If you want to give it a full width or 50%, no matter what it is. The padding top The padding top has to be the SVG height that we previously removed over the SVG width times the width of the of the container that you want to specify. Okay? So, the reason we're doing this is that Okay, so we said that uh the element is collapsed. It has no height anymore. So, in order to give it a height again, we apply the padding. And so, the resulting height, the height that is resulting from the padding is going to be a certain ratio of the width because the padding is set relative to the width, right? So, using this rule, the resulting height to width ratio of the container the same as the result of the as the original height-to-width ratio of the SVG. That way you make sure that they have the same ratio. Now, why do we need to create a positioning context and then position the iframe absolutely? Well, because the the the SVG the container has a height zero and then you've applied a padding to it, so the content of the container, which is the the SVG in this case, has been pushed down by the padding. So, in order to pull it back up and position it inside the container, you position it absolutely using position absolute. Okay, and then you set the width and the height to 100% to make sure that the iframe takes the entire width and height of the container. I hope that was clear. Okay. Um if you're embedding the SVG inline, you're going to need the padding hack, but only for Internet Explorer. Okay? Okay, and finally, just resize. It's going to be fluid. Ta-da! It's going to be cross-browser responsive. But, using the fixes and hacks and hacks. Hacks is that sounded kind of like The Lord of the Rings. Yeah, okay. So, making SVGs responsive with media queries. Um you can use media queries inside SVGs just like you would with HTML element, but there is one very important difference here. Okay, so in this example, I have an adaptive logo. Uh this is this is a this is this this is an example from an article that I wrote for Code Drops a while back. Um So, we're starting with the logo on the left, and then as the screen gets smaller in order so that the logo does not take a lot of screen estate, you're going to start removing, changing colors, and removing elements just like you would with HTML. So, here is the code of the SVG. We have a style tag inside the SVG, and then using media queries, we're specifying viewport sizes, and then specifying, for example, the first thing I did here was I removed the curved background. So, here I set the opacity to zero, and then the other content that was white became navy. Okay, so and then you just keep removing elements, changing them any way you want, just like you would with with HTML. And this is the result. When you resize the screen, the logo is going to adapt to the viewport size. However, uh there is one thing here to note. The sizes specified in the media queries refer to the size of the SVG viewport and not the size of the page viewport. This is This is very similar to having element queries, but for SVG. Like if you have if um for example, if you have embedded the SVG and the iframe is 300 pixels, that is the viewport that the media queries are going to refer to. Okay, it's not the viewport of the page, it's the viewport of the SVG itself. And the viewport as of the SVG depends on the way you embed it. So, if you've embedded the SVG using an image tag, the width and the height of the image tag are going to create the viewport inside which the SVG is going to be drawn. And if you've embedded it inline, for example, then the width and the height of the SVG are going to be the viewport in which the SVG is going to be drawn. And last but not least, that was the the last section. Uh don't forget to make SVGs accessible, please. This is very important. Um there's this article um written by Léonie Watson at on the SitePoint. This is my favorite article. It contains almost everything you need to make your SVGs accessible. Do read it, it's a must-read. And for a complete workflow for working with SVG, starting from tips for creating and optimizing and exporting, tips for Adobe Illustrator, Sketch, and Inkscape, uh then there is automating SVG workflow, refer to these slides by Todd Parker of the Filament Group. They are excellent. They are a must-read, and seriously, if you're going to work with SVG, do have a look at them. They are like a jewel for web design. Okay, so so if you have any questions, you You me up on Twitter at SaraSoueidan. If if Twitter, uh you can visit my website. I have a lot about SVG. I'm not self-promoting here, but I've written a lot about SVG and I hope you find them useful. If you have any questions, feel free to hit me up on the um coffee break, on the lunch break. If I know the answer and if I don't have any food in my mouth, I will answer them. Thank you.
- from
- Must-Watch Talks, Motion UI Design
- added
- 2026-10-10
- likes
- 0
Must-Watch Talks › 2014: “Sara Soueidan, CSSConf EU 29:16”
Motion UI Design › Speeches, presentations, videos: “(:movie_camera: video).”