Adam Reeve

When updating my website recently, I decided to use SVG (Scalable Vector Graphics) for icons. It's currently very popular to use an icon font, for example, Font Awesome, which was developed for use with Twitter Bootstrap. Using an icon font has a lot of benefits: you get scalable vector images, you can easily style icons using CSS, and your icons are all bundled into a single file that will be cached by browsers so only needs to be downloaded once. Icon fonts are also well supported by many browsers.

However, icon fonts are a bit of a hack, and using them comes with some downsides: it is trickier to position glyphs exactly using CSS, and icons can only contain one colour. Icons are also rendered as if they were text, which can result in unwanted anti-aliasing.

SVG based icons are a great alternative. With SVG, you aren't constrained by the limitations of a font, and the icons are just an image so you don't have to hassle with text positioning. It is also possible to style individual components within an SVG image using CSS and add interactivity with JavaScript, which opens up a lot of possibilities.

There are a number of ways SVG images can be used in a web page. The simplest is to use an img tag, just as you would with a JPG or PNG file:

<img src="path/to/my/icon.svg" />

This approach requires the browser to make an HTTP request for each SVG icon, so may not be appropriate for websites with a lot of icons.

Alternatively, SVG images can be applied as a background to HTML elements using CSS. A great resource for working with SVG icons that uses this approach is Grumpicon. Grumpicon generates CSS files that include SVG data inline, as well as PNG fallbacks for browsers that don't support SVG. However, the downside to this approach is that you can't style the SVG icons using CSS. For example, you might want the icon colour to change on hover if it's part of a hyperlink. In order to be able to style SVG graphics using CSS, the SVG document has to be part of the HTML DOM.

The approach I used for this website is based on this CSS-Tricks article. All the icons are put into a single SVG document, and each icon is contained in an SVG symbol element. This SVG document is included inline in the HTML, after the opening body tag. A complete example including two icons, one for a circle and one for a square, is shown below:

<svg xmlns="http://www.w3.org/2000/svg" style="display: none;" version="1.1">
  <symbol id="icon-square" viewBox="0 0 28 28">
    <path style="fill:currentColor; fill-opacity:1; fill-rule:nonzero; stroke:none;"
      d="M 4 4 L 24 4 L 24 24 L 4 24 Z" />
  </symbol>
  <symbol id="icon-circle" viewBox="0 0 28 28">
    <path style="fill:currentColor; fill-opacity:1; fill-rule:nonzero; stroke:none;"
      d="M 23.97 14 C 23.98 17.57 22.09 20.88 19 22.67 C 15.91 24.46 12.09 24.46 9 22.67 C 5.91 20.88 4.02 17.57 4.04 14 C 4.02 10.43 5.91 7.12 9.00 5.33 C 12.09 3.54 15.91 3.54 19 5.33 C 22.09 7.12 23.98 10.43 23.97 14 Z" />
  </symbol>
</svg>

Note that the SVG element has inline CSS applied so that it is not displayed. Each symbol has it's own viewBox attribute applied, which defines the extent of the x and y coordinates in the symbol. The path for each icon has also been styled so that the fill is set to currentColor. This means that the fill colour will be set to the current font colour used in the HTML document.

To then use an icon in the document, you simply reference the symbol by its id. For example, this will display the square icon:

<svg><use xlink:href="#icon-square" /></svg>

The main downside to this approach is that all icons must be included on every HTML page, increasing the size of each page. The way around this is to use references to icons in an external resource. In this case, the icon definitions are included in a separate SVG file, and are referenced like:

<svg><use xlink:href="svg-definitions.svg#icon-square" /></svg>

The external SVG file can then be cached by the browser so only has to be downloaded once. This isn't supported in any current version of Internet Explorer (up to IE 11), but luckily, there is svg4everybody available, which is a polyfill that provides support for external SVG files in Internet Explorer. Svg4Everybody also supports PNG images as a fallback for Internet Explorer versions less than IE 9. For more information on browser support for inline SVG, check out the Can I Use page.