Using SVG for icons

Published on Tuesday 19 April 2016. Tagged as CSSSVG.

SVG or Scalable Vector Graphics are supported by all modern browsers and can be used to replace image sprites. I'll explain how to use SVG sprites to render icons and logos by using tags and referring to them using the

What is SVG?

SVG stands for Scalable Vector Graphics, a lightweight XML format to describe vector graphics. This format is akin to the HTML format: it uses tags with attributes. It can be used as a background image, embedded in HTML or referenced from an external .svg file. It can do much more than just rendering icons: it has support for gradients, fill patterns, advanced filters and text effects.

Using SVG as icons

I am only using SVG to render logos and icons as vector graphics instead of the 'old school' method of using image sprites. The benefits are many: they can scale and I can change the color with CSS and they are very small. To have the same effect with normal images, I would have to modify them with PhotoShop or Gimp, save them and upload them again.

Making a SVG sprite file

You can find tons of SCG sprites by searching for 'SVG icons'. A good place to start is Flaticon: free vector icons. You can search for individual icons or download sets. You can build your own SVG set by converting them to < symbol> elements. You start with a standalone SVG, e.g. for a hamburger icon:

<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="612px" height="612px" viewBox="0 0 612 612" style="enable-background:new 0 0 612 612;" xml:space="preserve">
<g>
<g id="menu">
<g>
<path d="M420.75,26 .../... 9.125,19.125V516.375z"/>
</g>
</g>
</g>
<g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g>
</svg>

This can be cleaned up and converted into a symbol:

<symbol id="menu-icon" viewBox="0 0 612 612">
<path d="M420.75,267.75h-229.5c-21.133,0-38.25,17.117-38.25,38.25c0,21.133,17.117,38.25,38.25,38.25h229.5 c21.133,0,38.25-17.117,38.25-38.25C459,284.867,441.883,267.75,420.75,267.75z M420.75,401.625h-229.5 c-21.133,0-38.25,17.117-38.25,38.25s17.117,38.25,38.25,38.25h229.5c21.133,0,38.25-17.117,38.25-38.25 S441.883,401.625,420.75,401.625z M420.75,133.875h-229.5c-21.133,0-38.25,17.117-38.25,38.25s17.117,38.25,38.25,38.25h229.5 c21.133,0,38.25-17.117,38.25-38.25S441.883,133.875,420.75,133.875z M554.625,0H57.375C25.685,0,0,25.685,0,57.375v497.25 C0,586.315,25.685,612,57.375,612h497.25c31.69,0,57.375-25.685,57.375-57.375V57.375C612,25.685,586.315,0,554.625,0z M535.5,516.375c0,10.557-8.568,19.125-19.125,19.125H95.625c-10.557,0-19.125-8.568-19.125-19.125V95.625 c0-10.557,8.568-19.125,19.125-19.125h420.75c10.557,0,19.125,8.568,19.125,19.125V516.375z"/>
</symbol>

You can put all these symbols in a single .svg file. I named mine icons.svg:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" style="display:none">

<symbol id="duck-icon" viewBox="0 0 327 327"><path d="m269 138c-3-2-4-3-4-4 0 0 1-1 4-3 34-16 53-36 53-54 0-15-8-22-23-22-4 0-9 0-15 1-1 0-1 0-2 0-6 0-12-4-15-11C254 18 225 0 194 0c-44 0-80 36-80 80 0 21 8 40 22 55 3 3 3 5 3 6 0 1-1 2-4 2-11 3-21 5-32 5-5 0-11-1-16-2-3-1-7-2-12-4-11-4-25-8-38-8-11 0-20 4-25 12-11 16-8 48 10 98 22 61 62 83 149 83 13 0 28-1 44-2 30-2 55-12 73-28 19-18 29-42 29-70 0-36-18-69-47-89zM203 44c9 0 17 7 17 17 0 9-7 17-17 17-9 0-17-7-17-17 0-9 7-17 17-17z"/></symbol>

<symbol id="leftarrow-icon" viewBox="0 0 22 22"><path d="M10.544,11.031l6.742-6.742c0.81-0.809,0.81-2.135,0-2.944l-0.737-0.737 c-0.81-0.811-2.135-0.811-2.945,0L4.769,9.443c-0.435,0.434-0.628,1.017-0.597,1.589c-0.031,0.571,0.162,1.154,0.597,1.588 l8.835,8.834c0.81,0.811,2.135,0.811,2.945,0l0.737-0.737c0.81-0.808,0.81-2.134,0-2.943L10.544,11.031z"/></symbol>

<symbol id="rightarrow-icon" viewBox="0 0 46 46"><path d="M14.757,46.02c-1.412,0-2.825-0.521-3.929-1.569c-2.282-2.17-2.373-5.78-0.204-8.063l12.758-13.418L10.637,9.645 C8.46,7.37,8.54,3.76,10.816,1.582c2.277-2.178,5.886-2.097,8.063,0.179l16.505,17.253c2.104,2.2,2.108,5.665,0.013,7.872 L18.893,44.247C17.77,45.424,16.267,46.02,14.757,46.02z"/></symbol>

<symbol id="github-icon" viewBox="0 0 478.6 478.6"><path d="M427.5 200.7c1.8-11.2 2.9-23.6 3.2-37.4 -0.1-59.2-28.5-80.2-33.9-90 8-44.9-1.3-65.3-5.7-72.3 -16.1-5.7-55.9 14.7-77.7 29.1 -35.5-10.4-110.5-9.4-138.6 2.7C122.9-4.4 95.4 1.3 95.4 1.3s-17.7 31.8-4.7 78.4c-17.1 21.8-29.8 37.1-29.8 77.9 0 9.8 0.6 19 1.6 27.9 14.7 77.3 76 110.7 136.2 116.4 -9.1 6.9-19.9 19.9-21.4 35 -11.4 7.4-34.3 9.8-52.1 4.2 -24.9-7.9-34.5-57.3-71.8-50.2 -8.1 1.5-6.5 6.8 0.5 11.4 11.4 7.4 22.1 16.6 30.4 36.2 6.3 15.1 19.7 42 61.9 42 16.7 0 28.5-2 28.5-2s0.3 38.4 0.3 53.4c0 17.2-23.3 22.1-23.3 30.3 0 3.3 7.7 3.6 13.9 3.6 12.2 0 37.7-10.2 37.7-28.1 0-14.2 0.2-62.1 0.2-70.5 0-18.3 9.8-24.1 9.8-24.1s1.2 97.7-2.4 110.8c-4.2 15.4-11.7 13.2-11.7 20.1 0 10.2 30.6 2.5 40.7-19.9 7.8-17.5 4.3-113.3 4.3-113.3l8.2-0.2c0 0 0.1 43.9-0.2 63.9 -0.3 20.8-2.4 47 9.9 59.4 8.1 8.2 32.9 22.5 32.9 9.4 0-7.6-17.4-13.8-17.4-34.4V344.5c10.6 0 12.7 31.1 12.7 31.1l3.8 57.7c0 0-2.5 21.1 22.8 29.9 8.9 3.1 28 4 28.9-1.3 0.9-5.3-23-13-23.2-29.3 -0.1-9.9 0.4-15.7 0.4-58.9 0-43.2-5.8-59.1-26-71.9C355.7 295.7 416.5 269.5 427.5 200.7z"/></symbol>

</svg>

Referencing the SVG on the page

You have two options: to reference the symbols from the external file directly, e.g.:
<svg><use xlink:href="/webdev/inc/icons.svg#duck-icon"/></svg>
This method works in all modern browsers except MS Internet Explorer or MS Edge. These two do not understand external references. However: you can use a polyfill for this.

The second method works in all browsers, and also in MS Internet Explorer and MS Edge. You can embed the SVG in the page itself and referencing them from there, e.g.:
<svg><use xlink:href="#duck-icon"/></svg>
This method is ideal if you want to support MS browsers without polyfills. It also saves you one HTTP request. Tips: put the <svg> fragment directly at the start of the <body> element and put a style="display:none" attribute on it to prevent it using up space.

Styling SVG

SVG can be styled as you would do with normal HTML tags, in the external CSS file added to the page. Use the fill rule to set the fill colour. You can use currentColor; to make it inherit the color of the parent element. Setting height and width makes the SVG scale. Note that it always keeps its original proportions: that's what the viewport attribute is for. Example styling:

header svg{display:inline-block;fill:currentColor;width:32px;height:32px;margin-right:10px;position:relative;top:8px}
header a:hover{background:#455a64}
header a.on{background:#ff9800}
.github,.github:hover{position:absolute;top:0;right:0;margin:0;background:#000}

Next? I switched to a dynamic system for this blog. So pages are no longer seved from cached .html files, but direcly from the MySql database. CSS and SVG are now single external files. So I loose a bit on performance, but I gain a lot on maintenance. I'll explain more in posts to come.