Menu Search
Jump to the content X X
Smashing Conf New York

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

Styling And Animating SVGs With CSS

CSS can be used to style and animate scalable vector graphics, much like it is used to style and animate HTML elements. In this article, which is a modified transcript of a talk I recently gave1 at CSSconf EU and From the Front, I’ll go over the prerequisites and techniques for working with CSS in SVG.

I’ll also go over how to export and optimize SVGs, techniques for embedding them and how each one affects the styles and animations applied, and then we’ll actually style and animate with CSS.

Introduction Link

Scalable vector graphics (SVG) is an XML-based vector image format for two-dimensional graphics, with support for interactivity and animation. In other words, SVGs are XML tags that render shapes and graphics, and these shapes and graphics can be interacted with and animated much like HTML elements can be.

Animations and interactivity can be added via CSS or JavaScript. In this article, we’ll focus on CSS.

There are many reasons why SVGs are great and why you should be using them today:

  • SVG graphics are scalable and resolution-independent. They look great everywhere, from high-resolution “Retina” screens to printed media.
  • SVGs have very good browser support2. Fallbacks for non-supporting browsers are easy to implement, too, as we’ll see later in the article.
  • Because SVGs are basically text, they can be gzipped, making the files smaller that their bitmap counterparts (JPEG and PNG).
  • SVGs are interactive and styleable with CSS and JavaScript.
  • SVG comes with built-in graphics effects such as clipping and masking operations, background blend modes, and filters. This is basically the equivalent of having Photoshop photo-editing capabilities right in the browser.
  • SVGs are accessible. In one sense, they have a very accessible DOM API, which makes them a perfect tool for infographics and data visualizations and which gives them an advantage over HTML5 Canvas because the content of the latter is not accessible. In another sense, you can inspect each and every element in an SVG using your favorite browser’s developer tools, just like you can inspect HTML elements. And SVGs are accessible to screen readers if you make them so. We’ll go over accessibility a little more in the last section of this article.
  • Several tools are available for creating, editing and optimizing SVGs. And other tools make it easier to work with SVGs and save a lot of time in our workflows. We’ll go over some of these tools next.

Exporting SVGs From Graphics Editors And Optimizing Them Link

The three most popular vector graphics editors are:

  1. Adobe Illustrator3,
  2. Inkscape4,
  3. Sketch5.

Adobe Illustrator is a paid application from Adobe. It is a highly popular editor, with a nice UI and many capabilities that make it the favorite of most designers.

Inkscape is a popular free alternative. Even though its UI is not as nice as Illustrator’s, it has everything you need to work with vector graphics.

Sketch is a Mac OS X-only graphics app. It is not free either, but it has been making the rounds6 among designers lately and gaining popularity7, with a lot of resources and tools8 being created recently to improve the workflow.

Choose any editor to create your SVGs. After choosing your favorite editor and creating an SVG but before embedding it on a web page, you need to export it from the editor and clean it up to make it ready to work with.

I’ll refer to exporting and optimizing an SVG created in Illustrator. But the workflow applies to pretty much any editor, except for the Illustrator-specific options we’ll go over next.

To export an SVG from Illustrator, start by going to “File” → “Save as,” and then choose “.svg” from the file extensions dropdown menu. Once you’ve chosen the .svg extension, a panel will appear containing a set of options for exporting the SVG, such as which version of SVG to use, whether to embed images in the graphic or save them externally and link to them in the SVG, and how to add the styles to the SVG (by using presentation attributes or by using CSS properties in a <style> element).

The following image shows the best settings to choose when exporting an SVG for the web:

01-Ai-options-quick-preview-opt9

(View large version10)

The reasons why the options above are best are explained in Michaël Chaize’s excellent article “Export SVG for the Web With Illustrator CC11.”

Whichever graphics editor you choose, it will not output perfectly clean and optimized code. SVG files, especially ones exported from editors, usually contain a lot of redundant information, such as meta data from the editor, comments, empty groups, default values, non-optimal values and other stuff that can be safely removed or converted without affecting the rendering of the SVG. And if you’re using an SVG that you didn’t create yourself, then the code is almost certainly not optimal, so using a standalone optimization tool is advisable.

Several tools for optimizing SVG code are out there. Peter Collingridge’s SVG Editor12 is an online tool that you input SVG code into either directly or by uploading an SVG file and that then provides you with several optimization options, like removing redundant code, comments, empty groups, white space and more. One option allows you to specify the number of decimal places of point coordinates.

02-svg-editor-quick-preview-opt13

(View large version14)

Peter’s optimizer can also automatically move inline SVG properties to a style block at the top of the document. The nice thing about it is that, when you check an option, you can see the result of the optimization live, which enables you to better decide which optimizations to make. Certain optimizations could end up breaking your SVG. For example, one decimal place should normally be enough. If you’re working with a path-heavy SVG file, reducing the number of decimal places from four to one could slash your file’s size by as much as half. However, it could also entirely break the SVG. So, being able to preview an optimization is a big plus.

Peter’s tool is an online one. If you’d prefer an offline tool, try SVGO15 (the “O” is for “optimizer”), a Node.js-based tool that comes with a nice and simple drag-and-drop GUI16. If you don’t want to use an online tool, this one is a nice alternative.

The following screenshot (showing the path from the image above) is a simple before-and-after illustration of how much Peter’s tool optimizes SVG.

03-optimized-path-opt17

Notice the size of the original SVG compared to the optimized version. Not to mention, the optimized version is much more readable.

After optimizing the SVG, it’s ready to be embedded on a web page and further customized or animated with CSS.

Styling SVGs With CSS Link

The line between HTML and CSS is clear: HTML is about content and structure, and CSS is about the look. SVG blurs this line, to say the least. SVG 1.1 did not require CSS to style SVG nodes — styles were applied to SVG elements using attributes known as “presentation attributes.”

Presentation attributes are a shorthand for setting a CSS property on an element. Think of them as special style properties. They even contribute to the style cascade, but we’ll get to that shortly.

The following example shows an SVG snippet that uses presentation attributes to style the “border” (stroke) and “background color” (fill) of a star-shaped polygon:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="300px" viewBox="0 0 300 300">
  <polygon
fill = "#FF931E"
stroke = "#ED1C24"
stroke-width = "5"
points = "279.1,160.8 195.2,193.3 174.4,280.8   117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 "/>
</svg>

The fill, stroke and stroke-width attributes are presentation attributes.

In SVG, a subset of all CSS properties may be set by SVG attributes, and vice versa. The SVG specification lists the SVG attributes that may be set as CSS properties18. Some of these attributes are shared with CSS, such as opacity and transform, among others, while some are not, such as fill, stroke and stroke-width, among others.

In SVG 2, this list will include x, y, width, height, cx, cy and a few other presentation attributes that were not possible to set via CSS in SVG 1.1. The new list of attributes can be found in the SVG 2 specification19.

Another way to set the styles of an SVG element is to use CSS properties. Just like in HTML, styles may be set on an element using inline style attributes:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="width: 300px; height: 300px;" viewBox="0 0 300 300">
<polygon
  style = "fill: #FF931E; stroke: #ED1C24; stroke-width: 5;"
  points = "279.1,160.8 195.2,193.3 174.4,280.8   117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 "/>
</svg>

Styles may also be set in rule sets in a <style> tag. The <style> tag can be placed in the <svg> tag:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="300px" viewBox="0 0 300 300">
  <style type="text/css">
  <![CDATA[
  selector {/* styles */}
  ]]>
  </style>
  <g id=".."> … </g>
</svg>

And it can be placed outside of it, if you’re embedding the SVG inline in the document:

<!DOCTYPE html><!-- HTML5 document -->
<html>
<head> … </head>
<body>
<style type="text/css">
  /* style rules */
</style>
<!-- xmlns is optional in an HTML5 document →
<svg viewBox="0 0 300 300">
<!-- SVG content -->
</svg>
</body>
</html>

And if you want to completely separate style from markup, then you could always link to an external style sheet from the SVG file, using the <?xml-stylesheet> tag, as shown below:

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/css" href="style.css"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=".." height=".." viewBox="..">
  <!-- SVG content -->
</svg>

Style Cascades Link

We mentioned earlier that presentation attributes are sort of special style properties and that they are just shorthand for setting a CSS property on an SVG node. For this reason, it only makes sense that SVG presentation attributes would contribute to the style cascade.

Indeed, presentation attributes count as low-level “author style sheets” and are overridden by any other style definitions: external style sheets, document style sheets and inline styles.

The following diagram shows the order of styles in the cascade. Styles lower in the diagram override those above them. As you can see, presentation attribute styles are overridden by all other styles except for those specific to the user agent.

04-diagram-opt20

For example, in the following code snippet, an SVG circle element has been drawn. The fill color of the circle will be deep pink, which overrides the blue fill specified in the presentation attribute.

<circle cx="100" cy="100" r="75" fill="blue" style="fill:deepPink;" />

Selectors Link

Most CSS selectors can be used to select SVG elements. In addition to the general type, class and ID selectors, SVGs can be styled using CSS2’s dynamic pseudo-classes21 (:hover, :active and :focus) and pseudo-classes22 (:first-child, :visited, :link and :lang. The remaining CSS2 pseudo-classes, including those having to do with generated content23 (such as ::before and ::after), are not part of the SVG language definition and, hence, have no effect on the style of SVGs.

The following is a simple animation of the fill color of a circle from deep pink to green when it is hovered over using the tag selector and the :hover pseudo-class:

<style>
circle {
  fill: deepPink;
  transition: fill .3s ease-out;
}

circle:hover {
  fill: #009966;
}
</style>

Much more impressive effects can be created. A simple yet very nice effect comes from the Iconic24 icons set, in which a light bulb is lit up when hovered over. A demo of the effect25 is available.

Notes Link

Because presentation attributes are expressed as XML attributes, they are case-sensitive. For example, when specifying the fill color of an element, the attribute must be written as fill="…" and not Fill="…".

Furthermore, keyword values for these attributes, such as the italic in font-style="italic", are also case-sensitive and must be specified using the exact case defined in the specification that defines that value.

All other styles specified as CSS properties — whether in a style attribute or a <style> tag or in an external style sheet — are subject to the grammar rules specified in the CSS specifications, which are generally less case-sensitive. That being said, the SVG “Styling”26 specification recommends using the exact property names (usually, lowercase letters and hyphens) as defined in the CSS specifications and expressing all keywords in the same case, as required by presentation attributes, and not taking advantage of CSS’s ability to ignore case.

Animating SVGs With CSS Link

SVGs can be animated the same way that HTML elements can, using CSS keyframes and animation properties or using CSS transitions.

In most cases, complex animations will usually contain some kind of transformation — a translation, a rotation, scaling and/or skewing.

In most respects, SVG elements respond to transform and transform-origin in the same way that HTML elements do. However, a few inevitable differences result from the fact that, unlike HTML elements, SVG elements aren’t governed by a box model and, hence, have no margin, border, padding or content boxes.

By default, the transform origin of an HTML element is at (50%, 50%), which is the element’s center. By contrast, an SVG element’s transform origin is positioned at the origin of the user’s current coordinate system, which is the (0, 0) point, in the top-left corner of the canvas.

Suppose we have an HTML <div> and an SVG <rect> element:

<!DOCTYPE html>
…
<div style="width: 100px; height: 100px; background-color: orange"> </div>
<svg style="width: 150px; height: 150px; background-color: #eee">
  <rect width="100" height="100" x="25" y="25" fill="orange" />
</svg>

If were were to rotate both of them by 45 degrees, without changing the default transform origin, we would get the following result (the red circle indicates the position of the transform origin):

05-transform-svg-html-quick-preview-opt27

(View large version28)

What if we wanted to rotate the SVG element around its own center, rather than the top-left corner of the SVG canvas? We would need to explicitly set the transform origin using the transform-origin property.

Setting the transform origin on an HTML element is straightforward: Any value you specify will be set relative to the element’s border box.

In SVG, the transform origin can be set using either a percentage value or an absolute value (for example, pixels). If you specify a transform-origin value in percentages, then the value will be set relative to the element’s bounding box, which includes the stroke used to draw its border. If you specify the transform origin in absolute values, then it will be set relative to the SVG canvas’ current coordinate system of the user.

If we were to set the transform origin of the <div> and <rect> from the previous example to the center using percentage values, we would do this:

<!DOCTYPE html>
<style>
  div, rect {
  transform-origin: 50% 50%;
}
</style>

The resulting transformation would look like so:

06-transform-svg-html-quick-preview-opt29

(View large version30)

That being said, at the time of writing, setting the transform origin in percentage values currently does not work in Firefox. This is a known bug31. So, for the time being, your best bet is to use absolute values so that the transformations behave as expected. You can still use percentage values for WebKit browsers, though.

In the following example, we have a pinwheel on a stick that we’ll rotate using CSS animation. To have the wheel rotate around its own center, we’ll set its transform origin in pixels and percentages:

<svg>
<style>
.wheel {
  transform-origin: 193px 164px;
  -webkit-transform-origin: 50% 50%;
  -webkit-animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
  animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
}

@-webkit-keyframes rotate {
  50% {
    -webkit-transform: rotate(360deg);
  }
}

@keyframes rotate {
  50% {
    transform: rotate(360deg);
  }
}

</style>
<!-- SVG content -->
</svg>

You can check out the live result on Codepen32. Note that, at the time of writing, CSS 3D transformations are not hardware-accelerated when used on SVG elements; they have the same performance profile as SVG transform attributes. However, Firefox does accelerate transforms on SVGs to some extent.

Animating SVG Paths Link

There is no way to animate an SVG path from one shape to another in CSS. If you want to morph paths — that is, animate from one path to another — then you will need to use JavaScript for the time being. If you do that, I recommend using Snap.svg33 by Dmitry Baranovskiy, the same person behind the SVG library Raphaël.

Snap.svg is described as being to SVG what jQuery is to HTML, and it makes dealing with SVGs and its quirks a lot easier.

That being said, you could create an animated line-drawing effect using CSS. The animation would require you to know the total length of the path you’re animating and then to use the stroke-dashoffset and stroke-dasharray SVG properties to achieve the drawing effect. Once you know the length of the path, you can animate it with CSS using the following rules:

#path {
stroke-dasharray: pathLength;
stroke-dashoffset: pathLength;
/* transition stroke-dashoffset */
transition: stroke-dashoffset 2s linear;
}

svg:hover #path{
  stroke-dashoffset: 0;
}

In the example above, the path is drawn over the course of two seconds when the SVG is hovered over.

In the next demo, we’ll use the same technique and then use a CSS transition — with a delay — to light up the bulb once the path’s animation ends.

#cable {
  stroke: #FFF2B1;
  stroke-dasharray: 4000 4000;  
  stroke-dashoffset: 4000;
  stroke-width: 4;
  transition: stroke-dashoffset 8s linear;
}

svg:hover #cable {
  stroke-dashoffset: 0;
}

/* turn lamp on */
.inner-lamp{
  fill:grey;
  transition: fill .5s ease-in 6s;
}

svg:hover .inner-lamp {
  fill: #FBFFF8;
}
/* … */

You can view the live demo on JS Bin34. Note that you can also write stroke-dasharray: 4000; instead of stroke-dasharray: 4000 4000 — if the two line and gap values are equal, then you can specify only one value to be applied to both.

Sometimes, you might not know the exact length of the path to animate. In this case, you can use JavaScript to retrieve the length of the path using the getTotalLength() method:

var path = document.querySelector('.drawing-path');
path.getTotalLength();
//set CSS properties up
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
//set transition up
path.style.transition = 'stroke-dashoffset 2s ease-in-out';
// animate
path.style.strokeDashoffset = '0';

The snippet above is a very simplified example showing that you can do the same thing we did with CSS but using JavaScript.

Jake Archibald has written an excellent article explaining the technique35 in more detail. Jake includes a nice interactive demo that makes it easy to see exactly what’s going on in the animation and how the two SVG properties work together to achieve the desired effect. I recommend reading his article if you’re interested in learning more about this technique.

Embedding SVGs Link

An SVG can be embedded in a document in six ways, each of which has its own pros and cons.

The reason we’re covering embedding techniques is because the way you embed an SVG will determine whether certain CSS styles, animations and interactions will work once the SVG is embedded.

An SVG can be embedded in any of the following ways:

  1. as an image using the <img> tag:
    <img src="mySVG.svg" alt="" />
  2. as a background image in CSS:
    .el {background-image: url(mySVG.svg);}
  3. as an object using the <object> tag:
    <object type="image/svg+xml" data="mySVG.svg"><!-- fallback here --></object>
  4. as an iframe using an <iframe> tag:
    <iframe src="mySVG.svg"><!-- fallback here →</iframe>
  5. using the <embed> tag:
    <embed type="image/svg+xml" src="mySVG.svg" />
  6. inline using the <svg> tag:
    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" …>
    <!-- svg content →
    </svg>

The <object> tag is the primary way to include an external SVG file. The main advantage of this tag is that there is a standard mechanism for providing an image (or text) fallback in case the SVG does not render. If the SVG cannot be displayed for any reason — such as because the provided URI is wrong — then the browser will display the content between the opening and closing <object> tags.

<object type="image/svg+xml" data="mySVG.svg">
  <img src="fallback-image.png" alt="…" />
</object>

If you intend using any advanced SVG features, such as CSS or scripting, the then HTML5 <object> tag is your best bet.

Because browsers can render SVG documents in their own right, embedding and displaying an SVG using an iframe is possible. This might be a good method if you want to completely separate the SVG code and script from your main page. However, manipulating an SVG image from your main page’s JavaScript becomes a little more difficult and will be subject to the same-origin policy36.

The <iframe> tag, just like the <object> tag, comes with a default way to provide a fallback for browsers that don’t support SVG, or those that do support it but can’t render it for whatever reason.

<iframe src="mySVG.svg">
  <img src="fallback-image.png" alt="…" />
</iframe>

The <embed> tag was never a part of any HTML specification, but it is still widely supported. It is intended for including content that needs an external plugin to work. The Adobe Flash plugin requires the <embed> tag, and supporting this tag is the only real reason for its use with SVG. The <embed> tag does not come with a default fallback mechanism.

An SVG can also be embedded in a document inline — as a “code island” — using the <svg> tag. This is one of the most popular ways to embed SVGs today. Working with inline SVG and CSS is a lot easier because the SVG can be styled and animated by targeting it with style rules placed anywhere in the document. That is, the styles don’t need to be included between the opening and closing <svg> tags to work; whereas this condition is necessary for the other techniques.

Embedding SVGs inline is a good choice, as long as you’re willing to add to the size of the page and give up backwards compatibility (since it does not come with a default fallback mechanism either). Also, note that an inline SVG cannot be cached.

An SVG embedded with an <img> tag and one embedded as a CSS background image are treated in a similar way when it comes to CSS styling and animation. Styles and animations applied to an SVG using an external CSS resource will not be preserved once the SVG is embedded.

The following table shows whether CSS animations and interactions (such as hover effects) are preserved when an SVG is embedded using one of the six embedding techniques, as compared to SVG SMIL animations37. The last column shows that, in all cases, SVG animations (SMIL) are preserved.

Table showing whether CSS styles, animations and interactions are preserved for each of the SVG embedding techniques.
CSS Interactions (e.g. :hover) CSS Animations SVG Animations (SMIL)
<img> No Yes only if inside <svg> Yes
CSS background image No Yes only if inside <svg> Yes
<object> Yes only if inside <svg> Yes only if inside <svg> Yes
<iframe> Yes only if inside <svg> Yes only if inside <svg> Yes
<embed> Yes only if inside <svg> Yes only if inside <svg> Yes
<svg> (inline) Yes Yes Yes

The behavior indicated in the table above is the standard behavior. However, implementations may differ between browsers, and bugs may exist.

Note that, even though SMIL animations will be preserved, SMIL interactions will not work for an SVG embedded as an image (i.e. <img> or via CSS).

Making SVGs Responsive Link

After embedding an SVG, you need to make sure it is responsive.

Depending on the embedding technique you choose, you might need to apply certain hacks and fixes to get your SVG to be cross-browser responsive. The reason for this is that the way browsers determine the dimensions of an SVG differs for some embedding techniques, and SVG implementations among browsers also differ. Therefore, the way SVG is handled is different and requires some style tweaking to make it behave consistently across all browsers.

I won’t get into details of browser inconsistencies, for the sake of brevity. I will only cover the fix or hack needed for each embedding technique to make the SVG responsive in all browsers for that technique. For a detailed look at the inconsistencies and bugs, check out my article on Codrops4138.

Whichever technique you choose, the first thing you’ll need to do is remove the height and width attributes from the root <svg> element.

You will need to preserve the viewBox attribute and set the preserveAspectRatio attribute to xMidYMid meet — if it isn’t already set to that value. Note that you might not need to explicitly set preserveAspectRatio to xMidYMid meet at all because it will default to this value anyway if you don’t change it.

When an SVG is embedded as a CSS background image, no extra fixes or hacks are needed. It will behave just like any other bitmap background image and will respond to CSS’ background-image properties as expected.

An SVG embedded using an <img> tag will automatically be stretched to the width of the container in all browsers (once the width has been removed from the <svg>, of course). It will then scale as expected and be fluid in all browsers except for Internet Explorer (IE). IE will set the height of the SVG to 150 pixels, preventing it from scaling correctly. To fix this, you will need to explicitly set the width to 100% on the <img>.

<img src="mySVG.svg" alt="SVG Description." />
img {
  width: 100%;
}

The same goes for an SVG embedded using an <object> tag. For the same reason, you will also need to set the width of the <object> to 100%:

object {
  width: 100%;
}

Even though <iframe> has a lot in common with <object>, browsers seem to handle it differently. For it, all browsers will default to the default size for replaced elements in CSS39, which is 300 by 150 pixels.

The only way to make an iframe responsive while maintaining the aspect ratio of the SVG is by using the “padding hack” pioneered by Thierry Koblentz on A List Apart40. The idea behind the padding hack is to make use of the relationship of an element’s padding to its width in order to create an element with an intrinsic ratio of height to width.

When an element’s padding is set in percentages, the percentage is calculated relative to the width of the element, even when you set the top or bottom padding of the element.

To apply the padding hack and make the SVG responsive, the SVG needs to be wrapped in a container, and then you’ll need to apply some styles to the container and the SVG (i.e. the iframe), as follows:

<!-- wrap svg in a container -->
<div class="container">
  <iframe src="my_SVG_file.svg">
    <!-- fallback here -->
  </iframe>
</div>

.container {
  /* collapse the container's height */
  height: 0;        

  /* specify any width you want (a percentage value, basically) */     
  width: width-value;    

  /* apply padding using the following formula */
  /* this formula makes sure the aspect ratio of the container equals that of the SVG graphic */
  padding-top: (svg-height / svg-width) * width-value;
  position: relative;    /* create positioning context for SVG */
}

The svg-height and svg-width variables are the values of the height and width of the <svg>, respectively — the dimensions that we removed earlier. And the width-value is any width you want to give the SVG container on the page.

Finally, the SVG itself (the iframe) needs to be positioned absolutely inside the container:

iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

We position the iframe absolutely because collapsing the container’s height and then applying the padding to it would push the iframe beyond the boundaries of the container. So, to “pull it back up,” we position it absolutely. You can read more about the details in my article on Codrops4138.

Finally, an SVG embedded inline in an <svg> tag becomes responsive when the height and width are removed, because browsers will assume a width of 100% and will scale the SVG accordingly. However, IE has the same 150-pixel fixed-height issue for the <img> tag mentioned earlier; unfortunately, setting the width of the SVG to 100% is not sufficient to fix it this time.

To make the inline SVG fluid in IE, we also need to apply the padding hack to it. So, we wrap <svg> in a container, apply the padding-hack rules mentioned above to the container and, finally, position the <svg> absolutely inside it. The only difference here is that we do not need to explicitly set the height and width of <svg> after positioning it.

svg {
  position: absolute;
  top: 0;
  left: 0;
}

Using CSS Media Queries Link

SVG accepts and responds to CSS media queries as well. You can use media queries to change the styles of an SVG at different viewport sizes.

However, one important note here is that the viewport that the SVG responds to is the viewport of the SVG itself, not the page’s viewport, unless you are embedding the SVG inline in the document (using <svg>).

An SVG embedded with an <img>, <object> or <iframe> will respond to the viewport established by these elements. That is, the dimensions of these elements will form the viewport inside of which the SVG is to be drawn and, hence, will form the viewport to which the CSS media-query conditions will be applied. This is very similar in concept to element queries.

The following example includes a set of media queries inside an SVG that is then referenced using an <img> tag:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
  <style>
    @media all and (max-width: 50em) {
      /* select SVG elements and style them */
    } 
    @media all and (max-width: 30em) {
      /* styles  */
    }
  </style>
  <!-- SVG elements here -->
</svg>

When the SVG is referenced, it will get the styles specified in the media queries above when the <img> has a max-width of 50em or 30em, respectively.

<img src="my-logo.svg" alt="Page Logo." />

You can learn more about media queries inside SVGs in Andreas Bovens’s article for Dev.Opera42.

Final Words Link

SVGs are images, and just as images can be accessible, so can SVGs. And making sure your SVGs are accessible is important, too.

I can’t emphasize this enough: Make your SVGs accessible. You can do several things to make that happen. For a complete and excellent guide, I recommend Leonie Watson’s excellent article on SitePoint43. Her tips include using the <title> and <desc> tags in the <svg>, using ARIA attributes and much more.

In addition to accessibility, don’t forget to optimize your SVGs and provide fallbacks for non-supporting browsers. I recommend Todd Parker’s presentation44.

Last but not least, you can always check support for different SVG features on Can I Use45. I hope you’ve found this article to be useful. Thank you for reading.

(vf, al, il)

Footnotes Link

  1. 1 https://www.youtube.com/watch?v=lf7L8X6ZBu8
  2. 2 http://caniuse.com/#feat=svg
  3. 3 //www.adobe.com/mena_en/products/illustrator.html
  4. 4 https://inkscape.org/en/
  5. 5 http://bohemiancoding.com/sketch/
  6. 6 https://medium.com/@jm_denis/discovering-sketch-25545f6cb161
  7. 7 http://hackingui.com/design/sketch-design/why-i-moved-to-sketch/
  8. 8 http://www.sketchappsources.com/
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2014/10/01-Ai-options-large-preview-opt.png
  10. 10 https://www.smashingmagazine.com/wp-content/uploads/2014/10/01-Ai-options-large-preview-opt.png
  11. 11 http://creativedroplets.com/export-svg-for-the-web-with-illustrator-cc/
  12. 12 http://petercollingridge.appspot.com/svg-editor
  13. 13 https://www.smashingmagazine.com/wp-content/uploads/2014/10/02-svg-editor-large-preview-opt.png
  14. 14 https://www.smashingmagazine.com/wp-content/uploads/2014/10/02-svg-editor-large-preview-opt.png
  15. 15 https://github.com/svg/svgo
  16. 16 https://github.com/svg/svgo-gui
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2014/10/03-optimized-path-opt.jpg
  18. 18 http://www.w3.org/TR/SVG/propidx.html
  19. 19 http://www.w3.org/TR/SVG2/styling.html#SVGStylingProperties
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2014/10/04-diagram-opt.jpg
  21. 21 http://www.w3.org/TR/2008/REC-CSS2-20080411/selector.html#dynamic-pseudo-classes
  22. 22 http://www.w3.org/TR/2008/REC-CSS2-20080411/selector.html#q15
  23. 23 http://www.w3.org/TR/2008/REC-CSS2-20080411/generate.html
  24. 24 https://useiconic.com/
  25. 25 http://tutsplus.github.io/Styling-Iconic/styling/index.html
  26. 26 http://www.w3.org/TR/SVG11/styling.html#StylingWithCSS
  27. 27 https://www.smashingmagazine.com/wp-content/uploads/2014/10/05-transform-svg-html-large-preview-opt.png
  28. 28 https://www.smashingmagazine.com/wp-content/uploads/2014/10/05-transform-svg-html-large-preview-opt.png
  29. 29 https://www.smashingmagazine.com/wp-content/uploads/2014/10/06-transform-svg-html-large-preview-opt.png
  30. 30 https://www.smashingmagazine.com/wp-content/uploads/2014/10/06-transform-svg-html-large-preview-opt.png
  31. 31 https://bugzilla.mozilla.org/show_bug.cgi?id=891074
  32. 32 http://codepen.io/SaraSoueidan/pen/d0f94390e6c9af38fa562974399b6222?editors=100
  33. 33 http://snapsvg.io/
  34. 34 http://jsbin.com/haxaqa/1/edit?html,output
  35. 35 http://jakearchibald.com/2013/animated-line-drawing-svg/
  36. 36 http://en.wikipedia.org/wiki/Same-origin_policy
  37. 37 http://css-tricks.com/guide-svg-animations-smil/
  38. 38 http://tympanus.net/codrops/2014/08/19/making-svgs-responsive-with-css/
  39. 39 http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width
  40. 40 http://alistapart.com/article/creating-intrinsic-ratios-for-video/
  41. 41 http://tympanus.net/codrops/2014/08/19/making-svgs-responsive-with-css/
  42. 42 https://dev.opera.com/blog/how-media-queries-allow-you-to-optimize-svg-icons-for-several-sizes/
  43. 43 http://www.sitepoint.com/tips-accessible-svg/
  44. 44 https://docs.google.com/presentation/d/1CNQLbqC0krocy_fZrM5fZ-YmQ2JgEADRh3qR6RbOOGk/pub?start=true&loop=false&delayms=5000#slide=id.p
  45. 45 http://caniuse.com/#search=svg
SmashingConf New York

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook

Sara Soueidan is a freelance front-end web developer, consultant, author and speaker from Lebanon — focusing on HTML5, SVG, CSS, and JavaScript. She’s a contributing author to the Smashing Book #5 and an author and team member at Codrops. She writes for various high-profile blogs and magazines including the Adobe Dream Weaver Blog, Opera Developers’ Blog, Smashing Magazine, Netmag, and CSS-Tricks, among others. You can find her writing on her blog, and follow her on Twitter @SaraSoueidan.

  1. 1

    Great article! and Thanks a lot for featuring my HackingUI article :)

    7
  2. 2

    I really enjoyed your presentation so it’s great to see the noted form of this talk! This a greater primer for SVG’s and their benefits.

    7
  3. 3

    The SVG export in Adobe Illustrator is not working like expected.
    In case you export the css styles included in the svg file the font-size has no px added.

    Peter Loebel
    TWS AG
    http://www.flexible-editorial-design.com/

    6
    • 4

      the maximum canvas size from Illustrator is tiny when compared with Inkscape – shame on Adobe! :D

      2
      • 5

        haha do we need the canvas size to be big? I would have thought because it’s SVG how big the canvas goes doesn’t matter as it’s a vector graphic… it’ll keep it’s quality no matter how big or small you make it.

        2
        • 6

          Yes but it enables much more of an easier workspace, making a vector graphic is much easier when you can space the image and alter it in a sizeable form

          -1
  4. 7

    Thanks for this helpful article and all the great resources!

    1
  5. 8

    Great article! I cant wait to use some animated svg’s on my site. Just one thing, under the “Notes” section I’m pretty sure the second “fill” should be uppercased in some way … the “attribute must be written as fill=”…” and not fill=”…”.”

    1
  6. 9

    Frederick Weiss

    November 3, 2014 6:51 pm

    Great article… http://snapsvg.io/ is a really nice tool.

    3
  7. 10

    For more complex shapes (more than one path) you’ll need additional markup in order to display them as expected with the new Chrome 28 update as I found out a few weeks ago. Particularly setting your clip-rule properly to apply the proper fill-rule. The spec is pretty dense on this so you’ll have to read a lot, and make sure to click the referencing links to understand how graphics are put together. The easiest explanation I found was via the MSDN

    ###
    clip-rule=”evenodd”
    This rule determines the “insideness” of a point on the canvas by drawing a ray from that point to infinity in any direction and counting the number of path segments from the given shape that the ray crosses. If this number is odd, the point is inside; if even, the point is outside.
    ###

    Play in your sandbox too. This is good stuff to really make your design work pop and interfaces soar.

    3
  8. 11

    Ignacio Carbajo

    November 3, 2014 8:02 pm

    Yeah… Can’t wait to apply some of the tricks listed here with d3 charts (the main reason I fight with SVG on a daily basis), great article!

    2
  9. 12

    Good article. I needed to do a lot of this to make interactive svgs a few months ago for a project I was working on. This would have been a helpful guide for me back then.

    During that project I found and used this free desktop based svg cleaner:

    http://sourceforge.net/projects/svgcleaner/

    worked well to clean up complex svgs into a form that was more managable to further optimise and add style tags/hooks by hand, and has a LOT of optimisation options to play with. It’ll also do batch optimisations and export to svgz.

    3
  10. 13

    Great presentation and article ! Well explanatory about Styling and animation of SVGs with CSS. But some points are not been well understood as i am a beginner. Please share videos of the same if they are present.

    Thanks for the share!

    1
  11. 14

    A roundup article I was waiting for! Thank you for this well written explanation!

    2
  12. 15

    Great article!

    1
  13. 16

    Ray Dickenson

    November 4, 2014 3:38 pm

    In the Note about case sensitivity you neglected to change the case in the example:

    the attribute must be written as fill=”…” and not fill=”…”.

    1
  14. 18

    Frederick Weiss

    November 4, 2014 9:33 pm

    Can you comment on the Firefox issue w/ “transform-origin”?
    What is the best solution to this very big problem?

    1
    • 19

      Sara Soueidan

      November 5, 2014 1:10 am

      Currently, the best solution is to use absolute values to set the transform origin instead of percentages, until the bug has been fixed.

      1
  15. 20

    Thank you for this comprehensive article.
    Lots of great information which I am still digesting….
    The “Pinwheel” demo on CodePen does not seem to work on either Chrome or IE 11 — although it looks great on FireFox.
    Two other small “typos” I noted:

    “Note that you can also write stroke-dasharray: 4000; instead of stroke-dasharray: 4000 — if the… ” should probably have “4000 4000” in the second instance.

    “Note that, even though SMIL animations will be preserved, SMIL interactions will not work for….” should probably be “CSS interactions.”

    Again, thank you for a great article!

    1
    • 21

      Sara Soueidan

      November 5, 2014 1:13 am

      Hey Jonathan,

      Thank you for your comment! :)

      First typo: nice catch! Will fix, thanj you. :)

      The second note is actually correct in the article — I meant SMIL interactions (on-click animations, etc.)

      It’s odd regarding the Pinwheel demo, it works perfectly fine on Chrome for me. I’ll double-check as soon as possible.

      Cheers! :)

      1
  16. 22

    First, thank you for this very well written guide to svg animations.

    One common use-case of inline SVGs which is missing and I think is worth mentioning, is that of inline SVGs reusable through ‘symbol’ /’def’ blocks and a ‘use’ block.

    One thing about this use-case in the context of the current article, is that, to the best of my knowledge, SMIL animations will work as expected, but CSS animations will simply have no effect at all.

    Therefore, our only choice at the moment for animations in reusable inline SVGs is to stick to SMIL, which has no support in any version of It.

    1
    • 23

      Sorry for the typo, meant to write ‘has no support in any version of IE’.

      1
      • 24

        Btw it is also worth mentioning that SMIL might be deprecated (or is already on its way to that) in favor of the Web Animations API.

        3
    • 25

      Thank you for your comment! :)

      The use case u mentioned is not part of the context I was talking about, not to mention that the time for the talk was 30 mnts so I couldn’t elaborate on everything.

      That being said, I have written a detailed article about the `symbol`, `defs`, and `use` elements that you are welcome to check out: http://sarasoueidan.com/blog/structuring-grouping-referencing-in-svg

      When the SVG element is reused using the `use` element, selecting it and applying styles to its individual parts becomes harder because its contents are cloned into the shadow DOM, and hence animating with CSS will also be affected. I could not elaborate further in the talk because of the time limitation. The subject of styling the contents of the `use` element deserves its own article indeed.

      Thanks again for your comment. :)

      Cheers,
      Sara

      1
      • 26

        Thanks for the quick reply.
        The shadow is indeed one hindering factor tto styling reusable inline SVGs, but only on individual ‘use’ blocks. There is no problem styling elements inside the reusable blocks as long as the styles are applied in the so-called global scope.

        CSS animations inside use blocks, however, are a different matter altogether, and won’t work if defined on the global scope, or even if defined in a style block inside the SVG itself.

        1
  17. 27

    Brand development

    November 5, 2014 5:27 pm

    Great job….!!!! Interesting post. I know your hard work value because i am developer form onelink solution IT company. This blog is very helpful for me and my team. Thanks for sharing this informative blog post. keep it up………

    3
  18. 28

    Last Row in the table should be
    (inline): yes, yes, yes

    You said that here:
    http://slides.com/sarasoueidan/styling-animating-svgs-with-css–2#/35

    0
  19. 30

    Thank you so much for writing/publishing this. I’ve seen the videos of the presentations but it’s handy to have this available as a reference.

    1
  20. 31

    A quick comment on Mac vector editing programs.

    In addition to Sketch, there’s iDraw, Affinity Designer and WebCode. They all have their limitations – none of them have the export options that you get in Illustrator (but then again they all cost about a tenth of the price of Illustrator). IMO the best overall is probably Affinity Designer, but whichever you use you’ll need to put it though SVGOptimiser/SVGEditor and then edit it in text editor (at least if you’re planning on exploring the features of svg).

    On the subject of text editors the good news is that a text editor with Webkit preview will let you edit your svg with a live preview. Textmate and Coda both have this as does BBEdit – and I think that there are also a couple of open source/free editors (eg SubEthaEdit and Smultron).

    So far although I now own four vector editing programs, the workhorse is good old Textmate.

    You can also open svgs direct into Safari and Chrome – for some reason the Textmate live preview seems to be more fault tolerant than Safari – so it’s worth using Safari for debugging/validating.

    2

↑ Back to top