 title: Using SVG
url: https://css-tricks.com/using-svg/
hash_url: 57cc77b47827e33de0f3a599449e5cc6

<p>SVG is an image format for vector graphics. It literally means <strong>Scalable Vector Graphics</strong>. Basically, what you work with in Adobe Illustrator. You can use SVG on the web pretty easily, but there is plenty you should know.</p>
<p><span id="more-20319"/></p>
<h3>Why use SVG at all?</h3>
<ul>
<li>Small file sizes that compress well</li>
<li>Scales to any size without losing clarity (except very tiny)</li>
<li>Looks great on retina displays</li>
<li>Design control like interactivity and filters</li>
</ul>
<h3>Getting some SVG to work with</h3>
<p>Design something in Adobe Illustrator. Here's a Kiwi bird standing on an oval.</p>
<figure id="post-20383 media-20383" class="align-none"><img src="https://cdn.css-tricks.com/wp-content/uploads/2013/03/kiwi.png" alt=""/></figure>
<p>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.</p>
<p>You can save the file directly from Adobe Illustrator as an SVG file.</p>
<figure id="post-20384 media-20384" class="align-none"><img src="https://cdn.css-tricks.com/wp-content/uploads/2013/03/save-as-svg.png" alt=""/></figure>
<p>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 <a href="http://www.w3.org/TR/SVGMobile/">SVG Profiles</a>. I find SVG 1.1 works fine.</p>
<figure id="post-20385 media-20385" class="align-none"><img src="https://cdn.css-tricks.com/wp-content/uploads/2013/03/svg-options.png" alt=""/></figure>
<p>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. </p>
<figure id="post-20386 media-20386" class="align-none"><img src="https://cdn.css-tricks.com/wp-content/uploads/2013/03/svg-code.png" alt=""/></figure>
<p>Both can be useful.</p>
<h3>Using SVG as an &lt;img&gt;</h3>
<p>If I save the SVG to a file, I can use it directly in an <code>&lt;img&gt;</code> tag.</p>
<pre rel="HTML"><code class="language-markup">&lt;img src="kiwi.svg" alt="Kiwi standing on oval"&gt;</code></pre>
<p>In Illustrator, our artboard was 612px ✕ 502px.</p>
<figure id="post-20387 media-20387" class="align-none"><img src="https://cdn.css-tricks.com/wp-content/uploads/2013/03/artboard.png" alt=""/></figure>
<p>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 <code>img</code> and changing its <code>width</code> or <code>height</code>, again like you could a PNG or JPG. Here's <a href="http://codepen.io/chriscoyier/pen/evcBu">an example</a> of that:</p>
<pre class="codepen" data-height="300" data-type="result" data-href="lCEux" data-user="chriscoyier" data-safe="true"><a href="http://codepen.io/chriscoyier/pen/lCEux">Check out this Pen!</a></pre>
<h4>Browser support</h4>
<p>Using it this way has its own set of specific <a href="http://caniuse.com/#feat=svg-img">browser support</a>. Essentially: it works everywhere except IE 8 and down and Android 2.3 and down. </p>
<p>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 <a href="http://css-tricks.com/workshop-notes-webstock-13/">different</a> <a href="http://css-tricks.com/workshop-notes-from-incontrol-hawaii/">workshops</a> <a href="http://css-tricks.com/deseret-digital-workshop/">I've done</a>. </p>
<p>One way is to test for support with Modernizr and swap out the <code>src</code> of the image:</p>
<pre rel="jQuery"><code class="language-javascript">if (!Modernizr.svg) {&#13;
  $(".logo img").attr("src", "images/logo.png");&#13;
}</code></pre>
<p>David Bushell has a really <a href="http://dbushell.com/2013/02/04/a-primer-to-front-end-svg-hacking/">simple alternative</a>, if you're OK with JavaScript in the markup:</p>
<pre rel="HTML"><code class="language-markup">&lt;img src="image.svg" onerror="this.onerror=null; this.src='image.png'"&gt;</code></pre>
<p><a href="http://benhowdle.im/svgeezy/">SVGeezy</a> can also help. We'll cover more fallback techniques as this article progresses.</p>
<h3>Using SVG as a background-image</h3>
<p>Similarly easy to using SVG as an img, you can use it in CSS as a <code>background-image</code>.</p>
<pre rel="HTML"><code class="language-markup">&lt;a href="/" class="logo"&gt;&#13;
  Kiwi Corp&#13;
&lt;/a&gt;</code></pre>
<pre rel="CSS"><code class="language-css">.logo {&#13;
  display: block;&#13;
  text-indent: -9999px;&#13;
  width: 100px;&#13;
  height: 82px;&#13;
  background: url(kiwi.svg);&#13;
  background-size: 100px 82px;&#13;
}</code></pre>
<p>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 <code>background-size</code> keywords like <code>contain</code> if you want to make sure the image will fit and can't know the parent image will be of the exact right size.</p>
<h4>Browser support</h4>
<p>Using SVG as background-image has its own special set of <a href="http://caniuse.com/#feat=svg-css">browser support</a>, 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.</p>
<p>Modernizr can help us here, and in a more efficient way than using img. If we replace the <code>background-image</code> 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:</p>
<pre rel="CSS"><code class="language-css">.main-header {&#13;
  background: url(logo.svg) no-repeat top left;&#13;
  background-size: contain;&#13;
}&#13;
&#13;
.no-svg .main-header {&#13;
  background-image: url(logo.png);&#13;
}</code></pre>
<p>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).</p>
<pre rel="CSS"><code class="language-css">body {&#13;
  background: url(fallback.png);&#13;
  background-image: url(image.svg), none;&#13;
}</code></pre>
<h3>The problem with both &lt;img&gt; and background-image...</h3>
<p>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!</p>
<h3>Using "inline" SVG</h3>
<p>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.</p>
<pre rel="HTML"><code class="language-markup">&lt;body&gt;&#13;
&#13;
   &lt;!-- paste in SVG code, image shows up!  --&gt;&#13;
&#13;
&lt;/body&gt;</code></pre>
<p>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 <a href="http://css-tricks.com/data-uris/">Data URI</a>. 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.</p>
<p>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:</p>
<pre rel="PHP"><code class="language-markup">&lt;?php echo file_get_contents("kiwi.svg"); ?&gt;</code></pre>
<p>A little PHP-specific thing here... it was demonstrated to me that <code>file_get_contents()</code> is the correct function here, not <code>include()</code> or <code>include_once()</code> as I have used before. Specifically because SVG sometimes is exported with <code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;</code> that as the opening line, which will cause the PHP parser to choke on it.</p>
<h4>Optimize it first</h4>
<p>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 <a href="http://petercollingridge.appspot.com/svg_optimiser">SVG Optimiser</a> tool. Upload the old, download the new. In <a href="http://www.youtube.com/watch?v=iVzW3XuOm7E&amp;feature=youtu.be">Kyle Foster's video</a>, he even takes it the extra mile and removes line breaks after this optimization. </p>
<p>If you're even more hardcore, here is a <a href="https://github.com/svg/svgo">Node JS tool</a> for doing it yourself.</p>
<h4>Now you can control with CSS!</h4>
<p>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 <code>&lt;ellipse&gt;</code> and an <code>&lt;path&gt;</code>. We can jump into the code and give them class names, just like any other HTML element can have.</p>
<pre rel="SVG"><code class="language-markup">&lt;svg ...&gt;&#13;
  &lt;ellipse class="ground" .../&gt;&#13;
  &lt;path class="kiwi" .../&gt;&#13;
&lt;/svg&gt;</code></pre>
<p>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 <code>&lt;link&gt;</code>ed up. Note that SVG elements have a special set of CSS properties that work on them. For instance, it's not <code>background-color</code>, it's <code>fill</code>. You can use normal stuff like :hover though.</p>
<pre rel="CSS"><code class="language-css">.kiwi {&#13;
  fill: #94d31b; &#13;
}&#13;
.kiwi:hover {&#13;
  fill: #ace63c; &#13;
}</code></pre>
<p>Even cooler, SVG has all these fancy filters. For instance blurring. Chuck a filter in your <code>&lt;svg&gt;</code>:</p>
<pre rel="SVG"><code class="language-markup">&lt;svg ...&gt;&#13;
  ...&#13;
  &lt;filter id="pictureFilter" &gt;&#13;
    &lt;feGaussianBlur stdDeviation="5" /&gt;&#13;
  &lt;/filter&gt; &#13;
&lt;/svg&gt;</code></pre>
<p>Then you can apply that in your CSS as needed:</p>
<pre rel="CSS"><code class="language-css">.ground:hover {&#13;
  filter: url(#pictureFilter);&#13;
}</code></pre>
<p>Here's <a href="http://codepen.io/chriscoyier/pen/evcBu">an example</a> of all that:</p>
<pre class="codepen" data-height="300" data-type="result" data-href="evcBu" data-user="chriscoyier" data-safe="true"><a href="http://codepen.io/chriscoyier/pen/evcBu">Check out this Pen!</a></pre>

<h4>Browser support</h4>
<p>Inline SVG has it's own <a href="http://caniuse.com/#feat=svg-html5">set of browser support</a>, but again, it's essentially only an issue in IE 8 and down and Android 2.3 and down<sup>1</sup>. </p>
<p>One way to handle fallbacks for this type of SVG is:</p>
<pre rel="HTML"><code class="language-markup">&lt;svg&gt; ... &lt;/svg&gt;&#13;
&lt;div class="fallback"&gt;&lt;/div&gt;</code></pre>
<p>Then use Modernizr again:</p>
<pre rel="CSS"><code class="language-css">.fallback { &#13;
  display: none;&#13;
  /* Make sure it's the same size as the SVG takes up */&#13;
}&#13;
.no-svg .fallback { &#13;
  background-image: url(logo.png); &#13;
}</code></pre>
<h3>Using SVG as an &lt;object&gt;</h3>
<p>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 <code>&lt;object&gt;</code>.</p>
<pre rel="HTML"><code class="language-markup">&lt;object type="image/svg+xml" data="kiwi.svg" class="logo"&gt;&#13;
  Kiwi Logo &lt;!-- fallback image in CSS --&gt;&#13;
&lt;/object&gt;</code></pre>
<p>For the fallback, Modernizr detection will work fine here:</p>
<pre rel="CSS"><code class="language-css">.no-svg .logo {&#13;
  width: 200px;&#13;
  height: 164px;&#13;
  background-image: url(kiwi.png);&#13;
}</code></pre>
<p>This will work great with caching and actually has <em>deeper</em> support than using it any other way. But, if you want the CSS stuff to work, you can't use an external stylesheet or <code>&lt;style&gt;</code> on the document, you need to use a <code>&lt;style&gt;</code> element inside the SVG file itself.</p>
<pre rel="SVG"><code class="language-markup">&lt;svg ...&gt;&#13;
  &lt;style&gt;&#13;
    /* SVG specific fancy CSS styling here */&#13;
  &lt;/style&gt;&#13;
  ...&#13;
&lt;/svg&gt;</code></pre>
<h4>External stylesheets for &lt;object&gt; SVG</h4>
<p>SVG has a way to declare an external stylesheet, which can be nice for authoring and caching and whatnot. This only works with <code>&lt;object&gt;</code> embedding of SVG files as far as I've tested. You'll need to put this in the SVG file above the opening <code>&lt;svg&gt;</code> tag. </p>
<pre rel="HTML"><code class="language-markup">&lt;?xml-stylesheet type="text/css" href="svg.css" ?&gt;</code></pre>
<p>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 <code>&lt;img&gt;</code> or <code>background-image</code>, it won't barf, but it won't work (the SVG will still render though). </p>
<h3>Data URI's for SVG</h3>
<p>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 network request. </p>
<p>Mobilefish.com has <a href="http://www.mobilefish.com/services/base64/base64.php">an online conversion tool</a> 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:</p>
<figure id="post-20388 media-20388" class="align-none"><img src="https://cdn.css-tricks.com/wp-content/uploads/2013/03/base64-data.png" alt=""/></figure>
<p>You can use that anywhere we've talked about so far (except inline <code>&lt;svg&gt;</code> because that just doesn't make sense) Just put the gibberish where it says [data] in these examples.</p>
<h4>As &lt;img&gt;</h4>
<pre rel="HTML"><code class="language-markup">&lt;img src="data:image/svg+xml;base64,[data]"&gt;</code></pre>
<h4>As CSS</h4>
<pre rel="CSS"><code class="language-css">.logo {&#13;
  background: url("data:image/svg+xml;base64,[data]");&#13;
}</code></pre>
<p>Relevant note here: regular CSS doesn't care if you put quotes around the data URI, but Sass does, so I've quoted it above (Thx Oziel Perez).</p>
<h4>As &lt;object&gt;</h4>
<pre rel="HTML"><code class="language-markup">&lt;object type="image/svg+xml" data="data:image/svg+xml;base64,[data]"&gt;&#13;
  fallback&#13;
&lt;/object&gt;</code></pre>
<p>And yep, if you have an embedded <code>&lt;style&gt;</code> in your SVG before you base64 it, <a href="http://codepen.io/chriscoyier/pen/ioCjk">it will work</a> if you use it as an <code>&lt;object&gt;</code> still!</p>
<h4>Format for Data URI</h4>
<p>All the examples above have base64 as the encoding, but data URI's do not have to be base64. In fact in the case of SVG, it's probably <a href="https://css-tricks.com/probably-dont-base64-svg/">better NOT to use base64</a>. Primarily because the native format of SVG is much more repetitive than base64 ends up, it gzips better. </p>
<pre rel="HTML"><code class="language-markup">&lt;!-- base64 --&gt;&#13;
data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL...&#13;
&#13;
&lt;!-- UTF-8, not encoded --&gt;&#13;
data:image/svg+xml;charset=UTF-8,&lt;svg ...&gt; ... &lt;/svg&gt;&#13;
&#13;
&lt;!-- UTF-8, optimized encoding for compatibility --&gt;&#13;
data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://...'&#13;
&#13;
&lt;!-- Fully URL encoded ASCII --&gt;&#13;
data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A//...</code></pre>
<p>Command line thingy for base64ing SVG:</p>
<blockquote class="twitter-tweet"><p>@<a href="https://twitter.com/chriscoyier">chriscoyier</a> @<a href="https://twitter.com/hkfoster">hkfoster</a> maybe you could take a shortcut with &gt;&gt;&gt; echo -n `cat logo.svg` | base64 | pbcopy</p>
<p>— Benny Schudel (@bennyschudel) <a href="https://twitter.com/bennyschudel/status/307963605998006273">March 2, 2013</a></p></blockquote>
<p>Or alternatively <a href="http://superuser.com/questions/120796/os-x-base64-encode-via-command-line#comment280484_120815">Mathias Bynens has some techniques</a>:</p>
<blockquote><p>Use <code>openssl base64 &lt; path/to/file.png | tr -d '\n' | pbcopy</code> or <code>cat path/to/file.png | openssl base64 | tr -d '\n' | pbcopy</code> to skip writing to a file and just copy the base64-encoded output to the clipboard without the line breaks.</p></blockquote>
<p>And a <a href="http://jpillora.com/base64-encoder/">drag-and-drop tool</a>.</p>
<h3>Automation Tools</h3>
<ul>
<li><a href="https://github.com/filamentgroup/grunticon">grunticon</a>:<br/>
<blockquote><p>From a CSS perspective, it's easy to use, as it generates a class referencing each icon, and doesn't use CSS sprites.</p>
<p>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.</p></blockquote>
</li>
<li><a href="https://github.com/jkphl/iconizr">iconizr</a>:<br/>
<blockquote><p>A PHP command line tool for converting SVG images to a set of CSS icons (SVG &amp; PNG, single icons and / or CSS sprites) with support for image optimization and Sass output.</p></blockquote>
</li>
</ul>
<h3>Related Stuff</h3>

<p>Kyle Foster's <a href="http://www.youtube.com/watch?v=iVzW3XuOm7E&amp;feature=youtu.be">An Optimized SVG Workflow</a>, which is worth an embed:</p>
<p>... and the <a href="http://www.youtube.com/watch?v=1AdX8odLC8M&amp;feature=youtu.be">follow up</a> + <a href="http://kylefoster.me/svg-slides/">slides</a>.</p>
<hr/>
<p><sup>1</sup> <small>And speaking of Android 2.3 browser, <a href="https://twitter.com/paul_irish/status/309037258638512129">this</a>. But if you absolutely have to support the native browser, <a href="http://www.kendoui.com/blogs/teamblog/posts/12-02-17/using_svg_on_android_2_x_and_kendo_ui_dataviz.aspx">this</a>.</small></p>
