Grow your CSS skills. Land your dream job.

Using SVG

Published by Chris Coyier

SVG is an image format for vector graphics. It literally means Scalable Vector Graphics. Basically, what you work with in Adobe Illustrator. You can use SVG on the web pretty easily, but there is plenty you should know.

Why use SVG at all?

  • Small file sizes that compress well
  • Scales to any size without losing clarity (except very tiny)
  • Looks great on retina displays
  • Design control like interactivity and filters

Getting some SVG to work with

Design something in Adobe Illustrator. Here's a Kiwi bird standing on an oval.

Notice the artboard is cropped up right agains the edges of the design. Canvas matters in SVG just like it would in PNG or JPG.

You can save the file directly from Adobe Illustrator as an SVG file.

As you save it, you'll get another dialog for SVG Options. I honestly don't know much about all this. There is a whole spec for SVG Profiles. I find SVG 1.1 works fine.

The interesting part here is that you can either press OK and save the file, or press "SVG Code..." and it will open TextEdit (on a Mac anyway) with the SVG code in it.

Both can be useful.

Using SVG as an <img>

If I save the SVG to a file, I can use it directly in an <img> tag.

<img src="kiwi.svg" alt="Kiwi standing on oval">

In Illustrator, our artboard was 612px ✕ 502px.

That's exactly how big the image will on the page, left to itself. You can change the size of it though just by selecting the img and changing its width or height, again like you could a PNG or JPG. Here's an example of that:

Check out this Pen!

Browser support

Using it this way has its own set of specific browser support. Essentially: it works everywhere except IE 8 and down and Android 2.3 and down.

If you'd like to use SVG, but also need to support these browsers that don't support using SVG in this way, you have options. I've covered different techniques in different workshops I've done.

One way is to test for support with Modernizr and swap out the src of the image:

if (!Modernizr.svg) {
  $(".logo img").attr("src", "images/logo.png");

David Bushell has a really simple alternative, if you're OK with JavaScript in the markup:

<img src="image.svg" onerror="this.onerror=null; this.src='image.png'">

SVGeezy can also help. We'll cover more fallback techniques as this article progresses.

Using SVG as a background-image

Similarly easy to using SVG as an img, you can use it in CSS as a background-image.

<a href="/" class="logo">
  Kiwi Corp
.logo {
  display: block;
  text-indent: -9999px;
  width: 100px;
  height: 82px;
  background: url(kiwi.svg);
  background-size: 100px 82px;

Notice we set the background-size to the size of the logo element. We have to do that otherwise we'll just see a bit of the upper left of our much larger original SVG image. These numbers are aspect-ratio aware of the original size. But you could use a background-size keywords like contain if you want to make sure the image will fit and can't know the parent image will be of the exact right size.

Browser support

Using SVG as background-image has its own special set of browser support, but it's essentially the same as using SVG as img. The only problem browsers are IE 8 and down and Android 2.3 and down.

Modernizr can help us here, and in a more efficient way than using img. If we replace the background-image with a supported format, only one HTTP request will be made instead of two. Modernizr adds a class name of "no-svg" to the html element if it doesn't support SVG, so we use that:

.main-header {
  background: url(logo.svg) no-repeat top left;
  background-size: contain;

.no-svg .main-header {
  background-image: url(logo.png);

Another clever progressive enhancement flavored technique for using SVG as background-image is by using it in conjunction with multiple backgrounds. SVG and multiple backgrounds have very similar browser support, so if the browser supports multiple backgrounds, it supports SVG, and the declaration will work (and override any previous declaration).

body {
  background: url(fallback.png);
  background-image: url(image.svg), none;

The problem with both <img> and background-image...

Is that you don't get to control the innards of the SVG with CSS like you can with the following two ways. Read on!

Using "inline" SVG

Remember how you can grab the SVG code right from Illustrator while saving if you want? (You can also just open the SVG file in a text editor and grab that code.) You can drop that code right into an HTML document and the SVG image will show up just the same as if you put it in an img.


   <!-- paste in SVG code, image shows up!  -->


This can be nice because the image comes over right in the document and doesn't need to make an additional HTTP request. In other words, it has the same advantages as using a Data URI. It has the same disadvantages too. A potentially "bloated" document, a big chunk of crap right in the document you're trying to author, and inability to cache.

If you're using a back end language that can go fetch the file and insert it, at least you can clean up the authoring experience. Like:

<?php include("kiwi.svg"); ?>

Optimize it first

Likely not a huge shocker, but the SVG that Adobe Illustrator gives you isn't particularly optimized. It has a DOCTYPE and generator notes and all that junk. SVG is already pretty small, but why not do all we can? Peter Collingridge has an online SVG Optimiser tool. Upload the old, download the new. In Kyle Foster's video, he even takes it the extra mile and removes line breaks after this optimization.

If you're even more hardcore, here is a Node JS tool for doing it yourself.

Now you can control with CSS!

See how the SVG looks a lot like HTML? That's because they are both essentially XML (named tags with angle brackets with stuff inside). In our design, we have two elements that make up the design, an <ellipse> and an <path>. We can jump into the code and give them class names, just like any other HTML element can have.

<svg ...>
  <ellipse class="ground" .../>
  <path class="kiwi" .../>

Now in any CSS on this page we can control those individual elements with special SVG CSS. This doesn't have to be CSS embedded in the SVG itself, it can be anywhere, even in our global stylesheet <link>ed up. Note that SVG elements have a special set of CSS properties that work on them. For instance, it's not background-color, it's fill. You can use normal stuff like :hover though.

.kiwi {
  fill: #94d31b; 
.kiwi:hover {
  fill: #ace63c; 

Even cooler, SVG has all these fancy filters. For instance blurring. Chuck a filter in your <svg>:

<svg ...>
  <filter id="pictureFilter" >
    <feGaussianBlur stdDeviation="5" />

Then you can apply that in your CSS as needed:

.ground:hover {
  filter: url(#pictureFilter);

Here's an example of all that:

Check out this Pen!

Browser support

Inline SVG has it's own set of browser support, but again, it's essentially only an issue in IE 8 and down and Android 2.3 and down1.

One way to handle fallbacks for this type of SVG is:

<svg> ... </svg>
<div class="fallback"></div>

Then use Modernizr again:

.fallback { 
  display: none;
  /* Make sure it's the same size as the SVG takes up */
.no-svg .fallback { 
  background-image: url(logo.png); 

Using SVG as an <object>

If "inline" SVG just isn't your jam (remember it does have some legit drawbacks like being hard to cache), you can link to an SVG file and retain the ability to affect its parts with CSS by using <object>.

<object type="image/svg+xml" data="kiwi.svg" class="logo">
  Kiwi Logo <!-- fallback image in CSS -->

For the fallback, Modernizr detection will work fine here:

.no-svg .logo {
  width: 200px;
  height: 164px;
  background-image: url(kiwi.png);

This will work great with caching and actually has deeper support than using it any other way. But, if you want the CSS stuff to work, you can't use an external stylesheet or <style> on the document, you need to use a <style> element inside the SVG file itself.

<svg ...>
    /* SVG specific fancy CSS styling here */

External stylesheets for <object> SVG

SVG has a way to declare an external stylesheet, which can be nice for authoring and caching and whatnot. This only works with <object> embedding of SVG files as far as I've tested. You'll need to put this in the SVG file above the opening <svg> tag.

<?xml-stylesheet type="text/css" href="svg.css" ?>

If you put that in your HTML, the page will barf and not even try to render. If you link up an SVG file that has that in it as an <img> or background-image, it won't barf, but it won't work (the SVG will still render though).

Data URI's for SVG

Another way to use SVG's is to convert them into Data URI's. Data URI's might not save you actual file size, but can be more efficient because the data is right there. It doesn't require an additional HTTPRequest. has an online conversion tool for that. Simply paste in the contents of your SVG file and fill out the form and it will display the results in a textarea for you to copy. Remember to remove line breaks in the data it gives you back. It looks like pure gibberish:

You can use that anywhere we've talked about so far (except inline <svg> because that just doesn't make sense) Just put the gibberish where it says [data] in these examples.

As <img>

<img src="data:image/svg+xml;base64,[data]>


.logo {
  background: url(data:image/svg+xml;base64,[data]);

As <object>

<object type="image/svg+xml" data="data:image/svg+xml;base64,[data]>

And yep, if you have an embedded <style> in your SVG before you base64 it, it will work if you use it as an <object> still!

Command line thingy for base64ing SVG:

Or alternatively Mathias Bynens has some techniques:

Use openssl base64 < path/to/file.png | tr -d '\n' | pbcopy or cat path/to/file.png | openssl base64 | tr -d '\n' | pbcopy to skip writing to a file and just copy the base64-encoded output to the clipboard without the line breaks.

Automation Tools

  • grunticon:

    From a CSS perspective, it's easy to use, as it generates a class referencing each icon, and doesn't use CSS sprites.

    grunticon takes a folder of SVG/PNG files (typically, icons that you've drawn in an application like Adobe Illustrator), and outputs them to CSS in 3 formats: svg data urls, png data urls, and a third fallback CSS file with references to regular png images, which are also automatically generated and placed in a folder.

  • iconizr:

    A PHP command line tool for converting SVG images to a set of CSS icons (SVG & PNG, single icons and / or CSS sprites) with support for image optimization and Sass output.

Related Stuff

Kyle Foster's An Optimized SVG Workflow, which is worth an embed:

... and the follow up + slides.

1 And speaking of Android 2.3 browser, this. But if you absolutely have to support the native browser, this.

Wanna learn more about SVG?

I have a full course available called Everything You Need to Know about SVG that covers the whole spectrum of SVG from the perspective of a web designer and front end developer.


  1. Seriously comprehensive article Chris, opus indeed. Is going straight to the TOP resources folder in the bookmarks.
    Already been busy with SVG, the way I handled the fallbacks back then was swapping out the extension .svg for .png if Modernizr showed browser didn’t cut the mustard..

  2. Permalink to comment#

    This is awesome, Thanks Chris. Alright, so If we can treat svgs like imgs, can we use them for fluid text? . . . sounds like a codepen I’m going to have knockout.

  3. Shaimoom Newaz
    Permalink to comment#

    Just when I thought I learned it all, there came SVG. Thanks for the inside scoop on this. Look forward to harnessing its power.

  4. Also, if using Inkscape there’s some pointers here for how to optimise:

    • Hi @eqroeil, your posted comment addresses what I’ve been trying to figure out – how to make SVG work in responsive design. No one is addressing this.

      Here’s my codepen:

      On the left is #ALA art – the paint brush. Next is my logo and then a second version of the paint brush. The 2nd version and the logo both have width and height removed, only veiwBox and “preserveAspectRatio=”xMinYMin meet”. These scale with the container but they break the object box. Why why why?

      I have been searching for the right solution. Your example works. I will be pulling it apart today to understand why! Any comments would be most appreciated.

  5. Permalink to comment#

    I’ve been trying to use SVG images as a background image on responsive div’s:

    div class="span4"

    but unlike an img I cannot use width="100%" which will automatically scale it, and despite my div resizing as the browser window changes size, the background svg dimensions will stay the same. This is not really specific to SVG’s as it happens with PNG’s/JPG’s too but something you need to keep in mind.

    Not a problem in modern browsers, but your usual suspects (IE 8 and lower and possibly IE9) have trouble with this.

    • You should have a look with preserveAspectRatio=”xMinYMin meet” added to your svg and only keep viewBox=”0 0 800 960″ (removing width and height, but it should not be necessary…)

      into your css try background-size: cover (or contain)


      as a fallback for ie : conditionnal classes and png fallback ; )

      .ie8 .span4{
      background: url(thepngone.png);

    • TNK
      Permalink to comment#

      I dont think is what you needed but it might be useful for someone.
      Responsive element with SVG as background keeping ratio:

      #shape {
          background-image: url(../img/shape.svg);
          background-size: 100% 100%;
          width: 10%;
      #shape:after {
          padding-top: 300%; /* % based on the image original ratio 100 x 300px*/
          display: block;
          content: '';
  6. Nice post Chris! Tiny bug in your object fallback though:

    .no-svg .logo {
      background-image: url(kiwi.svg);

    Should be

    .no-svg .logo {
      background-image: url(kiwi.png);

  7. Good to get more info on fallbacks for SVG. I’ll have to get to work on them for my websites.

    My last two designs have included nothing but SVGs in the main layout with background textures, header images, logos and other elements being nothing but SVG. They look awesome on a Retina display! What I have noticed however is that the graphics do tend to look slightly different across browsers. On for example, It appears that Fireworks is correctly interpreting some of my gradients in the header background as an ellipse gradient, whereas in Chrome and Safari, they appear to be interpreted as radial gradients, resulting in slightly less vivid colors. I thought that was rather interesting, but definitely not a deal breaker.

    Anyway, thanks for such a thorough review Chris! Much appreciated.

  8. hans_jv
    Permalink to comment#

    I had an issue with svg in ie10 (and possibly 9) recently.

    I was building a site that had a svg logo in header and footer. In the header (which as position: fixed) I used a div tag with the svg as background, and in the footer I used it as a img tag. The background in the a tag is used in the original size, while the img tag is a little smaller for design purposes.

    The issue is that sometimes explorer moves and crops the background in the header when another element with the same svg file as source is set at a different size. This problem is happening in ie10 but I think it happens in ie9 as well.

    I’ve made a fiddle in:
    (I have also made a pen at but most of the time the error doesn’t show until you resize the window).

    I solved it in this specific case, however I don’t know if this is an ie bug or I missed something. Other browsers seems to work fine.

    • Chris
      Permalink to comment#


      seems IE10 uses the exact same image and somehow fouls up, workaround seems an extra parameter for one image. Will have other issues (like cache I guess) but seems to work. You should file a bug report at Microsoft, generally I have fewer problems with IE10 than e.g. Chrome with stuff.

      BTW, the classList API works nicely for your example… supported in anything except IE<=9 it seems.

  9. Paul
    Permalink to comment#

    Great Article! Thank you, I really have been struggling with how to incorporate svg into my projects lately.

  10. pk
    Permalink to comment#

    The canvas size gets old fast if you’re not used to it. One thing that I’ve found helpful when saving as SVG is to select your art and then go to: object>artboard>fit selected to art. Hope that makes someone else’s life a bit easier.

  11. Jeff
    Permalink to comment#

    How do you handle SVGs inside a link? I’ve been trying to figure out the best way to do this.

  12. James
    Permalink to comment#

    I’ve been using this method as a fallback for SVGs as background images –

    .main-header {
        background: no-repeat top left;
        background-image: url(logo.png);
        background-image: url(logo.svg);
        background-size: contain;

    The idea is that the SVG will either override or be ignored depending on support.

    It’s a bit simpler than Chris’ method. Seems to work well for me but maybe there is there a flaw in this that I’m not seeing that somebody could point out?

    • You will be loading both unnecessarily, when only one is going to be displayed. But I think this is pretty neat to get it to work, though.

    • James
      Permalink to comment#

      Never thought about that Vinay, so I decided to check with Chrome and Firefox’s network profiler and only the svg file seems to be downloaded. Can’t be bothered firing up VMware to test IE but I’d assume it’s the same. Still wondering if there is a problem with this method because it feels almost too easy.

    • Kevin
      Permalink to comment#

      I’m pretty sure you’ll be loading both in every example used above. The difference between the one above and the one by James is the simplicity. The only way to be sure not download both is to use a data URI (pre-loaded) or check for browser support before elements start loading and replace/insert different extensions.

      You can also try:

      .main-header {
          background: no-repeat top left;
          background-image: url(logo.png);
          background-image: url(logo.svg);
          background-size: contain;
      :root .main-header {
          background-image: url(logo.svg);

      :root has the same level of support as svg for desktop browsers at least. Not sure about mobile ones. Since invalid selectors and properties are ignored, the svg file will only be downloaded in more modern browsers. The downside is that browsers supporting svg will download both :(

    • This was my first idea when I read article. Why not use simple cascading rules to achieve this fallback? I decided to look further at this and I can tell you why this is wrong. I am 100% that in almost every browser (actually on every I tested, and I tested on lot) will load ONLY one image. This was my first WOW. But could this be so simple? Answer is NO. As only one image is loaded there is no fallback. If .svg will not load (becasue is not supported for example) then nothing will load. That situation appear for example in IE8.


  13. Also consider, this method for creating a PNG fallback for browsers that throw an error on SVG within an img element. jQuery:

    // use ".svg" img class attribute when the src is a SVG
    $(function() {
      $(".svg").error(function() {
        $(this).attr("src",function() {
          return $(this).attr("src").replace(".svg",".png");


  14. If a browser doesn’t support SVG and you want to provide a fallback for your content, you might as well attempt to replace all of them. Defining a specific pattern and sticking to it will help. For example, maybe all of your fallback images are named the same as the SVG file except with a .png extension instead of .svn:

    if (!Modernizr.svg) {
      $('img[src$=".svg"]').each(function() {
        var $this = $(this); // this = img
        $this.attr('src', $this.attr('src').replace(/svg$/, 'png'));
    • Nice!

      Just as a note to someone who might use this: remember that you actually have to produce those .png replacements and have them side by side in the same directory, every time.

  15. Thanks for sharing this Chris, great write up.

  16. Chris, please mention this important SVG issue with Firefox:

    In Firefox, SVG used as a css background-img is bitmapped at its original designed dimensions, before it is scaled up or down. This results in very blurry images when upscaling a small SVG. Some suggest to simple use a gigantic SVG so you never upscale, only downscale. But I have seen horrible performance when you use a huge SVG and downscale (though that when the element was 3d transformed and animated).

    Kinda funny that this implementation of SVG isn’t S or V…

    Check this page in FF, it shows the bug well

    (bugzilla is under maintenance, but this might be the bug, I can’t check now)

    Workaround is the above mentioned other options, like inline SVG.

    Firefox for many many versions has not fixed that bug. As a result, I don’t think SVG as a CSS background is a good option at the moment. Which is sad because background-cover and centering makes it such an attractive option.

    • Permalink to comment#

      Thank you! I was about to post something similar. I’ve had some serious frustrations trying to use SVG background, only to see it look terrible in FF. Inline definitely helps, but there are some real advantages to backround images and it’s interesting that Firefox still has this bug.

      Check out this side by side close up of’s menu, which uses a SVG sprite. Chrome is on the left, FF on the right.

    • Jim
      Permalink to comment#

      I actually ran into the opposite when setting up svg’s for mobile. Firefox for mobile displayed them perfectly where as chrome for mobile pixelated them so badly that I ended up scrapping the svgs and using double sized pngs scaled down using background-size.

    • I’ve tried all of the workarounds for FF, and they all seem to be less than 100% effective. Go David Bushell’s home page, and you’ll see that his .svg logo gets blurry and less blurry as you zoom in and out with FF.

      Using an img tag didn’t solve the problem for me.

      Stripping out height and width from the .svg code appears harmless and helps somewhat.

      I’m considering just using a FF conditional to serve .png…

  17. @Peter Foti – agreed, 'img[src$=".svg"]' much better!

  18. Permalink to comment#

    Humbled and proud to be a part of this article. Thank you, kind sir.

  19. I had a messy experience here with inline svg and animation.
    I didn’t have time to optimise. It’s quite cute on FF; There’s so much to do with svg inline and css. Thanks for the good advices. (I use inkscape on linux)

  20. Very nice post, I have also created a post not long ago about SVGs and animation of them. You can find it here: animating-properties-of-injected-svg-elements

    I think SVGs are terrific for multiple purposes but they are not getting the attention they deserve, especially in this new multi-screen era that we are experiencing, their scalability is life-saving.

  21. Dwoo
    Permalink to comment#

    What kind of magic base64 encoder do you use to make it shrink?

    Base64 is larger than raw formats, including plain text.

  22. Thanks for tutorial. I use SVGO GUI for optimizing SVG vector graphics files.

  23. I prefer the invisible gradient technique as fallback for SVG

  24. Dennis
    Permalink to comment#

    Fantastic information.

    For what it’s worth, here’s a a demo of a draggable and zoomable SVG:


  25. Wa, Nice post, I’v got something from here

  26. David
    Permalink to comment#

    Excellent article.

    Just one remark. You say :

    with both <img> and background-image […] you don’t get to control the innards of the SVG with CSS

    It’s not true. You definitely can style them with CSS.
    You only have to use <style> element inside your svg
    (because not every browser support <?xml-stylesheet type=”text/css” href=”svg-stylesheet.css” ?> )

  27. Robert D'Arcy
    Permalink to comment#

    A very good article, although not comprehensive – it lacks information about using links inside an SVG as well as the possibilities for animation (although that would require an article all by itself).

    I have been meaning for a long time to use SVG in a website but for the moment I only use it to create procedural graphics, like Guilloche patterns, such as this example-

    Guilloche experiment #1

  28. Really wish this post existed 6 months ago. Google used to return so many horrible adobe links from 2001 when you googled anything about SVG.

    SVG will only get bigger with all the high DPI devices coming out.

    Below is the sass/scss mixin I’ve used on lots of builds.

    @mixin svg($img-name) {
        .svg .svg") no-repeat;
        .no-svg .png") no-repeat;
    .logo {
        @include svg-logo('company-logo');
        @extend %image-replace;
        height: 100px;
        width: 100px;
    // Use % for silent classes
    %image-replace {
  29. Hi there!
    I just want to point out that SVG actually can be considered an application engine with vector graphics presentation built in, as you can script the document and css it very much like you do with HTML. SVG could be used instead of HTML if you want more low-level graphics primitives available in your main layout rather than the high level “document” semantics available in HTML (browsers probably need the SVG viewport be wrapped by the HTML tag though at the moment).

  30. Wow, great article Chris. I just skimmed it, but will definitely dive into it soon.

    Just one quick note: If you have a SVG file, you don’t have to explicetly save it as “code”, an SVG file is per already “written in code”.

  31. Pete B
    Permalink to comment#

    A way to shrink SVG’s even smaller is to convert them into Data URI’s.

    One minor correction: base64 encoded svg for data-uri will always be more bytes than an un-encoded svg. I’m thinking the optimisation you’re thinking of is the http request you avoid by embedding?

    In theory you can get use un-encoded svg in data uri’s, but browser support is a bit flaky:

  32. Brad S.
    Permalink to comment#

    Fantastic article. It for this sort of stuff that I subscribe! Thanks :)

  33. Steve Wanless
    Permalink to comment#

    Great image choice – a Kiwi isn’t just a fruit!

  34. strages
    Permalink to comment#

    when using the optimize tool, always check for distortion in your svg output and also check if something is off..

    in my case it didn’t leave the id in for my linear gradient, which resulted in a pure color instead of a gradient :P

  35. SVG should be used more. Wikipedia is the only website that comes to mind that uses SVG on a regular basis

    • MSN on our IE10/Windows8 pages use an inline SVG for the header logo, and use CSS to change the color for the different channels rather than have a bunch of differently-colored PNGs.

  36. Great Article! Actually have started using SVG just few days back so I am new at it. But the biggest advantage is that I can simply create vector graphics in software like Illustrator and use them as SVG in my designs. They are helping me reduce the size of my designs to a great extent.

    Thanks for sharing such a valuable information, really helping me a lot to better understand SVG

  37. Gregory Pakosz
    Permalink to comment#

    Please note that as I tweeted you, SVG as background-image doesn’t play well in Opera:

    Also, as mentioned by, SVG-as-image is fuzzy/pixelated when zoomed or printed in all browsers but Chrome 23+ and IE9+ because the browsers first renders SVG into a bitmap then zooms that bitmap in instead of re-rendering when the zoom level changes

  38. This is amazing resource. I read a lot about SVG, but never used it on my projects. Will do in future for sure!

  39. Gavin
    Permalink to comment#

    Hot Link Flat UI is not working.

    Sorry – didnt know where else to post this as there is no comment section on those links

  40. Eelco
    Permalink to comment#

    Do I stand correct that you can’t style the svg when it’s base64 encoded within the css? Like in
    Codepen doesn’t seem to like the inline-image property, but you get the point.

  41. Jeremy
    Permalink to comment#

    How can you talk about SVG on the web and not mention RaphaelJS? Granted, it’s more about dynamically rendering SVG and interacting with it, but to quote their site:

    Raphaël is a small JavaScript library that should simplify your work with vector graphics on the web. If you want to create your own specific chart or image crop and rotate widget, for example, you can achieve it simply and easily with this library.
    Raphaël uses the SVG W3C Recommendation and VML as a base for creating graphics. This means every graphical object you create is also a DOM object, so you can attach JavaScript event handlers or modify them later. Raphaël’s goal is to provide an adapter that will make drawing vector art compatible cross-browser and easy.
    Raphaël currently supports Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+.

    I’m pretty sure it has touch support (dragging) baked in. Check out the demos on their site.

    • Jeremy
      Permalink to comment#

      And some good plugins:

      export “instructions” as json
      export “instructions” as actual SVG
      convert to PNG/JPG in browser with canvg — this is super awesome for exporting; you can basically make your own image editor in the browser
      Example of a drawing app — Raphael SketchPad
      And if you find some polygon formulas, it makes it really easy to make complicated shapes (I’ve built something for hearts, stars, and triangles)

    • DarrenM
      Permalink to comment#


      I’m using the Raphael library to handle SVG graphics on one of our sites. I understand it uses VML on IE platforms that don’t support SVG.

      I use it for custom charts, which were previously drawn using a graphics library on the server and streamed as images to the browser. Doing it with SVG has allowed me to interact with the charts in Javascript, for example I can highlight a plot on the chart when the user hovers over a name in the legend.

      The Raphael commands are embedded in the HTML, which makes the page size a bit larger than before, but it hasn’t affected page performance noticeably and the pages are now served with a single HTTP request instead of several.

  42. Nice article Chris.

    Recently I used SVG for a logo (as an <img> tag), and with essentially no users of that site on Android 2.3 I only had to worry about oldIE, which meant I was able to use conditional comments and avoid JavaScript altogether.

    I wrote it up here.

  43. This is awesome, Chris! Thanks a lot for putting all this together. Especially the combination of SVG and CSS opens so many opportunities. I’ll have to try some of this stuff myself! Thanks again

  44. Great article. One other useful bit of knowledge. If you embed an SVG into LESS and probably also SASS you can set the fill colours using variables. This is very handy for me as I can use standard icons on several websites but each site sets it’s own colours.

  45. This is easier more understandable base64 code (for the Terminal):

    openssl base64 -in kiwi.svg -out kiwi_64.txt

  46. Ben
    Permalink to comment#

    I added a couple of things to the inline SVG example to make it accessible:

    Super helpful article :)

  47. Although the SVG being sensational, I regret the fact that he was too slow to use it in games with JavaScript. I think we could do more with the SVG compared to the Canvas, but by its slowness, we have to resort to the canvas.

  48. JohnMotylJr
    Permalink to comment#

    I opened this article thinking it would be a little explanation and some code snippets. However, my mind was officially blown from start to finish. Insanely good article, this one is totally getting a bookmark. Thank you Mr. Coyier for filling my brain with some more goodness.

  49. That’s a pretty comprehensive article on SVG, I loved it. Saving it for later. I am also really confused between all the SVG vs Canvas stuff in the context of web gaming.

  50. This is the first time I have heard about this. More people should know about this. I am definitely tweeting this one! I will have to bookmark this and create SVG’s when I have the time.

  51. Peter Dmitrienko
    Permalink to comment#

    Amazing, Thanks a lot.

  52. James
    Permalink to comment#

    Wow! Definitely the best article i’ve come across regarding SVG’s.

    I am going to use this format for a website logo. For semantics, would it better to do it in the HTML as an IMG tag and suffer the additional HTTP request, as opposed to doing it via CSS?

    • If you consider it part of the content, then it deserves an img tag. If you think it is presentation only, then make it a background image via CSS.

    • James
      Permalink to comment#

      Well I am pretty certain the main logo of a website is content, and not presentation. So using an IMG tag would be best practice. My question in this instance was semantics vs performance.

      I am now thinking about the last technique Chris talks about, using base64 in the IMG tag, along with an ‘alt’ tag

  53. Wow I did not realize you could get the straight SVG from illustrator. great feature!

  54. Permalink to comment#

    in our app for android made with html5 +backbone + phonegap we decided to use svg for some illustration. This decision is giving me now some really hard times. The svg i’m trying to embed are not basic svg.
    I managed to add the dropshadow as a filter directly into the svg. The cool thing is that it renders well into any of the browser I used in the android device. But when you open the app created from the same html5 with phonegap and run into the same device the dropshadow filter is not rendered. I’m using for testing a HTC one X with the latest android distribution.

    Does anyone has an idea why phonegap seems to strip filters from the svg? I’ve tried to look on the web for this issue but got no clue…yet



  55. Thanks for the overview Chris! A lot of things in here that I did not realize were possible!

  56. cnwtx
    Permalink to comment#

    You can also use php to generate data-urls on the fly. For example:

    function data_url($file, $mime)

    The call it with this:

    data_url('./images/image.svg', 'image/svg+xml'); 
  57. Roman
    Permalink to comment#

    Okay, I am still not clear about what format of SVG to use. For example, for animating with CSS3, which method is the best? Also, for making responsive graphics (like logos) which one is the best? I have seen many people suggesting different things but there should be at least one that works well for styling and manipulating with CSS…

  58. Permalink to comment#

    Just discovered one caveat when styling the fill property with CSS – you need to remove any hardcoded fill attribute that Illustrator exports.


    <svg class="foo"><g fill="#FFF700"><path... /></g></svg>

    won’t have its fill attribute overridden by

    .foo {
    fill: #bada55;

    • Gareth
      Permalink to comment#

      If you target the svg element that has the fill property it overrides hard coded attributes. i.e. change to

      .foo g {
      fill: #bada55;

      .foo path { would also work.

  59. In order to use SVGs you’ll need to make sure that your server has the correct MIME type set to serve that file type: “image/svg+xml”.

  60. Permalink to comment#

    Thanks for this great writeup on good practices for using SVG on your website.

    Incase you are struggling to get the SVG to display on your page, an easy fix is to modify the AddType in your HTACCESS file.

    Add this towards the top of your HTACCESS:

    AddType image/svg+xml svg
    AddType image/svg+xml svgz
    AddEncoding x-gzip .svgz
    • Joe
      Permalink to comment#

      Thank you! This was driving me nuts. I mistakenly assumed that my host had this by default.

  61. Morfioce
    Permalink to comment#

    Chris you are awesome !

  62. Awesome always :)

  63. Permalink to comment#

    I currently wrote about SVG Stacking as a replacement for CSS Sprites. Therefore each icon is stored in the same SVG file but within its own layer:

  64. Such a shame you have to embed the SVG XML in a page to style it, it would have been so powerful to have multiple instances in a page and style them differently based on their context.

  65. Nate
    Permalink to comment#

    I’ve started playing with the Raphaël JavaScript Library. It’s pretty and seems powerful. From the site:

    Raphaël [‘ræfeɪəl] uses the SVG W3C Recommendation and VML as a base for creating graphics. This means every graphical object you create is also a DOM object, so you can attach JavaScript event handlers or modify them later. Raphaël’s goal is to provide an adapter that will make drawing vector art compatible cross-browser and easy.

    Raphaël currently supports Firefox 3.0+, Safari 3.0+, Chrome 5.0+, Opera 9.5+ and Internet Explorer 6.0+.

    It’s well documented on the site but is sparse on tutorials on the web.<br/>
    Does anyone have experience w/ it?

  66. Keen to know if anyone else has come across the same issue I am having with a site I’m building.
    I am testing the site in Chrome (latest version). Modernizer returns support for svg and I can directly access the svg file in the browser (displays fine) but it just won’t show up on the page. In all instances the svg’s are set as background images in the CSS.

  67. Michael
    Permalink to comment#

    I have used this for js detection of svg support.

    /* simple SVG image support detection */

    if (document.implementation.hasFeature("", "1.1")) {
    document.documentElement.className = "svg";

    with this in css

    #content {background-image: url(images/logo4.gif);}

    html.svg #content {background-image: url(images/logo4.svg);}

    thanks to this site for the info on svg use.

  68. made a bash script to simplify the base64 option Mathias Bynens authored.

  69. Permalink to comment#

    “inability to cache”? Inline SVG is just part of the HTML document, isn’t it? So if the document is being cached, the inline SVG is being cached too? I don’t get it.

    • Right but you probably don’t cache the HTML very hard, if at all. For instance, the cached HTML of this very page is being invalidated right now because I’m adding this comment.

  70. Downloading free or stock vector art from the web, I often couldn’t get it to display. It seems some browsers don’t like the “inkscape:” and “sodipodi:” prefixes in the code that appear in many SVG images. For me, it seemed that if opened the file in a text editor and deleted those phrases, it worked fine.

    Good tip on the blur in Firefox. Most of my images look fine in Firefox, so I stopped looking carefully at each one in FF, but there are a few that scaled up images that look bad.

  71. airtonix
    Permalink to comment#

    Reading this has brought back bad memories of php… Such an annoying language, the verbose requirements of semi-colons…. even in templates.

    Working with Django is so much easier.

  72. airtonix
    Permalink to comment#

    @Chris Coyler if your page cache is being invalidated by simple changes like comments, then you need to look at using a better templating system.

    Django has the concept of Application Level Cache, Whole Page Cache and Block Level Cache:

    In the scenario you describe, I’d be wrapping the SVG include inside a block level cache that is only invalidated if the svg were updated (assuming it’s pulled from a ORM query).

    Surely the php goblins have something similar?

    • Jeremy
      Permalink to comment#

      Uh… he’s talking about client-side page caching — literally, if the HTML has changed it’s a “new” page. Nothing to do with your language of choice.

      Possible workaround would be ajaxing in truly dynamic content like the comments, but then you have to jump through crawler hoops to index it.

  73. Johan Hernández
    Permalink to comment#

    Hi, I just used (based on a video of teamtreehouse with a correction in conditional comments by Ian Lunn) a svg as a logo with conditional comments as a fallback to a png… here is the code:

     <object data="img/logo.svg" type="image/svg+xml">
        <a href="img/logo.svg">
        <!--[if lte IE 8]>
          <img src="img/logo.png" alt="">

    It works just great! and to add a link you can follow this easy example found on fiddle (no js)

    • Johan Hernández
      Permalink to comment#

      Sorry, in the closing object there is a mistake… it’s object and no objetct. :D

  74. Raphael is a very necessary library when working with SVG! Cool article though, thanks

  75. Permalink to comment#

    For IE7 – 8 and crossbrowers there is

  76. Permalink to comment#

    Strange I’m not able to resize my svg’s with css in IE9. The SVG’s have viewports, widths and heights, they just don’t seem to be responding to css rules. There are (or should be, in IE9) svgs in the top right corner of each of the 6 white panels here

    • Replace:

      svg width=”640″ height=”480″ version=”1.1″ baseProfile=”full” xmlns=”” xmlns:xlink=”” xmlns:ev=””


      svg xmlns=”” xmlns:xlink=”” x=”0px” y=”0px”
      viewBox=”0 0 640 480″ enable-background=”new 0 0 640 480″ xml:space=”preserve”

      And it should work just fine. I’ve experienced scaling problems with using width and height attributes in svg, and never seem to have problems just eliminating them.

    • Permalink to comment#

      You rock! My viewport was missing!! No more coding at 3am. Thanks so much for catching that, I could have sworn I had one in there. So, for IE9 there seems to be good reason to include a height and width, check out this blog post.

    • I can’t seem to replicate the problems that experienced by omitting the height and width attributes. I’ve used .svg images very extensively on several sites (Responsively resizing with rem) and they all have the proper aspect ratio in cross-browser testing. Whenever I’ve noticed an image with a bad aspect ratio, it always has a height and width in the .svg code I forgot to delete. I always define height and width with CSS and omit them from the .svg itself; I noticed that you’ve only defined width on your site.

      I’m certainly not an expert… …curious what the actual right way to do this is.

      What do the other tricksters think?

    • After some further unintentional science, I seem to experience occasional problems using .svg as a background image with height and width, which are fixed by deleting height and width within the .svg and only using css to scale the image. Confusingly, I can experience problems by omitting the height and width within the .svg if I use an .img tag to embed the image.

  77. Graham
    Permalink to comment#

    Hi, I’ve found you can also use @import within the svg document to load an external CSS file.

    <style type="text/css">
    @import "external.css";
  78. Thank you for your detailed coverage of SVG images, Chris. It was very helpful for me, since we plan to use it in some Apps (Webkit only). Therefore we also don’t need to worry about fallbacks or incompatibility.

  79. Mike Buttery
    Permalink to comment#

    Firstly Chris, a massive thank you for the write up. I gained a huge amount of knowledge.<br/><br/>I did come across one ‘issue’ that maybe worth mentioning as I couldn’t find anything mentioning it. Using the <object> tag and a Data URI (To get around Chrome’s CORS issue, as I wanted access to elements inside the SVG), Chrome seems to lose the ability to render any gradients.<br/><br/>Example here:<br/><br/>I don’t think I missed anything. :(

  80. Fab
    Permalink to comment#

    Hi, great article indeed, I’m just having only one problem:

    I have my SVG base64 encoded using service, but sometimes I have an error on Chrome that says: ERROR 414 – URI too long.

    I think it depends from my webserver, but I have to push my stuff on prod and I have to be sure that I won’t have that error
    Do you have any idea/suggestion on how can I “fix” this problem?

    Thanks in advance.

    • Fab
      Permalink to comment#

      Any one has been facing the same problem with base64 svg data URI?

  81. lucideer
    Permalink to comment#

    One extra trick for the list, purely for completeness if nothing else. Similar to the <object/> method with the addition that it also supports CSS (I think … maybe).

    <svg xmlns="" xmlns:xlink="">
        <use xlink:href="kiwi.svg#Layer_1" />

    Seemingly no IE support at all however.

  82. christian
    Permalink to comment#

    Chris, Pretend a whole bag of peanut m&ms was modern day currency for $100. Then pretend I knew your address. I would send you a bag of peanut m&ms in a heartbeat my friend! How you write—articulating in easy-to-understand language—is balm to my soul. I’ve been scouring the internet trying to learn to use svgs for the first time. I almost got scared away. Gosh. Talk about confusing. Then I found this gem, hours later… Man, remember that bag of m&ms? Yeah. I meant it! Thank you so much man!!!

  83. Nice one Chris, already started using it for a client. Very good writeup, maybe better than MDN as far as practicality goes. Thanks again!

  84. Permalink to comment#

    I’ve been searching for some information on printing SVGs for a while. Some seem to render, but are cropped, some don’t show up at all and I don’t know the distinctions.

    For instance, this simple resolution test doesn’t print them at all.

    But your codepen example renders them, but they’re cropped.

    Any hints?

  85. Kieran Mahon
    Permalink to comment#

    Hi all, I’m using the “Data URI’s for SVG” option and all is well apart from the background position in IE.

    It seems like IE will only display the svg centred. Cannot seem to override this. I initially had the aligment included in a background shorthand, but also tried separating the css background declarations to no avail.

    Anyone else confirm this as I may be wasting my time trying to fix this!!

  86. Permalink to comment#

    Hi, thank you for this useful guide. Based on this guide I have made world flags rendered only by CSS: . Of course it has pros and cons. And the CSS can be improved (it is just experimental).

    One thing, I have discovered, not sure if this is valid for all file sizes, but the base64 encoding is much larger then pure SVG code.

    Unfortunately, Internet Explorer does not support raw SVG code in background attribute, so this is the only one reason why to encode SVG code, I think (maybe I am wrong). The same with uri encoding, the output is smaller than base64 but for Firefox you need to change this character: “#” and of course in Internet Explorer it does not work either.

    Anyway thank you again for this guide.


    • Jeremy
      Permalink to comment#

      @Jan nice work. Sorry to post this here rather than your support forum, but I noticed the top-right and bottom-left stripes in the AU flag are off…

  87. Permalink to comment#



    thank you for the info, seems like there were some problems while cleaning the SVG.

    I have cleaned it manually and it seems, it is OK now: (make F5 – refresh the site as the wrong SVG can be cached)

    Thank you, Jan

  88. fjpoblam
    Permalink to comment#

    Great (inspiring) article. I’ve now been using svgs on my and clients’ sites for several years. I even converted my logo to an svg — the language seems straightforward enough. One last puzzle for me is the danged css. I have a gradient background, currently set in “html” along with “min-height:100%”. Why? This seems to ensure the gradient proceeds on down the viewport even on pages whose content is very brief. (Like one-liners.) However, the gradient gets stretched to the full length of the content instead of the viewport for longer pages. How consistently (device-agnostic) to fill the viewport?

  89. Steve Smith
    Permalink to comment#

    Thank you for the article – I am new to svg (and Illustrator) and this helped me enormously.

    I have made a glass button in Illustrator as per these simple instructions and saved it as an svg file using your recommended settings above. It looks great in Illustrator but looks terrible in a browser: the transparent gradient doesn’t work at all. I have googled this for a solution until my fingers are bleeding but cannot find one anywhere – is there one?

    Thank you again for your great article.

  90. Permalink to comment#

    Hey Chris / anyone else reading this,

    I’ve got an image inside a unicode character,▼, giving me a nice effect without having to create a transparent png, it actually looks pretty neat.

    Was wondering if it’s possible to animate the image inside this ? Tried to animate opacity but it’s not looking very good (never reaches full opacity for some reason, guessing a bug in webkit?)

    Just wondering what else is possible?

  91. Luke
    Permalink to comment#

    I’ve done so much research online and I genuinely cannot figure out how to make an svg logo in illustrator and have it appear on a website with a transparent background…

    I want to use an svg file for a very small icon in a menu (combating the zooming problems) however it is appearing with a white background.. Is there a way around this??

  92. Permalink to comment#

    Great article/tutorial, helped loads … Extra thanks to Ben for his tweaks to make it accessible (march 7th post).


  93. How do you do a fill change on :hover when your svg icon is like a ‘hollow’ box? Once I’m inside the box, and not technically on the thin svg, I lose the hover. I tried doing a display:block on a parent div and putting the over on that. It seems I can’t override anything in the xml loaded stylesheet via an external one.

    I hope that makes sense. I’m trying to work with an envelope icon made up of very thin lines. The inside of the envelope is transparent. Unless I’m on the thin lines, I loose the hover.

    • I solved the problem above by using a hover on a group, defining an opacity 0 rectangle inside, then having my path. This way if you have a thin icon, you’re using the invisible square to define the ‘hotspot’.

      Note: I didn’t post the html here, but I used the object method Chris described above.

      /* Icons */

      .off_state {
          fill: #A7A9AB;
      .link_area {
          opacity: 0;   
      .link_group:hover > .off_state {
          fill: #FF0000;  


      <svg xmlns="" viewBox="0 0 29 29"> 
      <g class="link_group"><rect class="link_area" x="0px" y="0px" width="29px" height="29px"/><path d="M2.985 6.088v16.562h23.028V6.088H2.985z M14.268 16.258l-9.615-9.17h19.579L14.268 16.258z M10.56 14.1 l-6.574 6.707V7.833L10.56 14.104z M11.283 14.794l2.972 2.835l3.131-2.882l6.619 6.903H4.562L11.283 14.794z M18.123 14.1 l6.891-6.342v13.529L18.123 14.07z" class="off_state"/></g></svg>
  94. Jason Lombard
    Permalink to comment#

    Hi Technie Geeks,

    Can any kind soul tell me in simple english how one can place an.svg Image file into a HTML5 webpage?

    I’m old-fashioned in normally using the standard HTML format but would like to know how and where to place the embedded svg code?

  95. Permalink to comment#

    What a fantastic post and discussion. Thank you!

    I’m curious, has anyone experimented with creating their own font as an alternative means to achieve vector quality/scalable graphics with CSS control? Doesn’t fontface have better support in older versions of IE than SVG?

  96. Valery
    Permalink to comment#

    I’d like to use SVG in my projects, but the inability to cache seems like a huge dealbreaker. If you use it on your logo, which is on every page, wouldn’t that make the entire site in-cacheable? What if it’s for a large complex site where caching is crucial for performance?

  97. ezra
    Permalink to comment#

    Thanks for the article! About the usable properties for styling, I found the following:

    Don’t know if it’s up-to-date/relevant/implemented though.

  98. The issue with Firefox making scaled SVGs blurry, mentioned above, has been fixed from version 24 and up. The most recent version at the time of writing this is 28. (24-04-2014)

  99. Denn
    Permalink to comment#

    Perhaps I’m confused, but since IE8 doesn’t really support javascript I don’t see how this is gong to work.
    if (!Modernizr.svg) {
    $(‘img[src$=”.svg”]’).each(function() {
    var $this = $(this); // this = img
    $this.attr(‘src’, $this.attr(‘src’).replace(/svg$/, ‘png’));
    I’ve tried adding it (in a script tag pair in the header) and it fails on IE8 tests as does the solution proposed here (posted by someone above)

    Am I missing something? Can anyone point me to a site that shows a clean swap from svg to png in IE8 using that global script?

    The version that uses onerror works because the overlap between jscript (M$’s script version and javascript is sufficient to make it work but the global one does not seem to. I would love a global solution for that as now we just degrade the whole site and suggest they might want to think about a newer browser.

  100. Sean
    Permalink to comment#

    Based on your article, I made a command line SVG optimizer and base64 encoder. It is very easy to use “svgoptimizer -h” will show how it is used.

  101. G

    I have a Q? I used the object route for the .svg – it worked great in some ways… the fall back .png worked.. my .svg tho viewed online as a box in the correct size but it had the .txt file code in it?? I did make my .svg in ILL cs3 and used DW cs3 to html and upload… I tried it every way even your other opts and still – I think it works but my .svg shows as text code in image area with scrolls… I even tried all the different opts when saving .svg found on various sites… hmmm can u help? Has anyone had this [what I am sure is a minor…] happen before… Do I need to use the cloud or cs5 or higher… My site is HTML 5 and reponsive… I am baffled.. It was my first attempt as I want all my vectors to be .svg so they scale and look awesome!

  102. Angie

    Thank you for this article, it’s very well written and informative, but I have a question. When I save my svg from Illustrator, my code isn’t picking up the size of my artboard (the height and width don’t show in the markup) and my image is not responsive. From the article, it seems that this should be the default behavior. I’m using Adobe CC, so it should be the most up-to-date. Is there a setting I need to make in order for the svg to pick up the size of the artboard? Currently, when I open it in the browser, it renders the full height and width, not the settings I gave it. Is there a fix for that?

  103. Alex

    Great article. I have recently started using SVG’s and found this really useful. I am however wondering if any one can assist me with an issue I am tackling. I have a single SVG logo which uses DEFS and USE for various colours. I am then including the logo using the method. As the logo is used in two separate areas of the page template I wanted to use CSS to style the SVG fill colour dependent on the objects unique ID. Is this possible to do with CSS? I can do this with script or adding the SVG code directly onto the template, but ideally wanted to use CSS. Thanks!

  104. Joanne

    Thanks a lot for the information, you answered all my questions in one fell swoop.

  105. Mark Miller
    Permalink to comment#

    Great stuff Chris! Thanks for the detailed explanation.

  106. just spotting an opensource SVG background pattern library on github:

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".