Design & UX
By Massimo Cassandro

The Great Icon Debate: Fonts Vs SVG

By Massimo Cassandro

Illustration: Arm wrestling font guy vs SVG man (by Alex Walker)

We all know the feeling: just as you feel like you've finally achieved mastery of some great web technique… it's time to switch to something new and better.

It has certainly happened to me many times, and it happened again recently with icons. After a long period where icon fonts seemed to be the natural, best-practice solution, SVG has introduced some useful innovations that may have changed the rules of the game.

Choosing any technique is a task that involves weighing up many topics. When we deal with icons we need to consider:

  • Accessibility: are there some issues with text-only browsers or screen readers?
  • Semantic meaning: an icon is a glyph used to represent something else (this the simplest definition of this concept I've found; it comes from the Semantic-UI framework docs), so, are we creating a useful relationship between signs and the things to which they refer?
  • Browser compatibility: do we need to ensure a large browser compatibility?
  • HTTP issues: does our icon system unnecessarily tax our server (HTTP requests) and contribute to longer page load times? Can icon files be cached?
  • CSS styling & animation: can we arrange and animate our icons using CSS?

So, what is the best choice now? Can we still get by with icon fonts – or it is time to turn to SVG?

A Brief History

I realized that when we talk about icons, it's easy to take for granted some topics which we have been dealing with in the past. They can help us to better frame the debate, but not everyone knows them. So, I've put together a very brief 'history of icons techniques in web authoring' to help clarify the debate. (If you feel you're ok with the history part, jump ahead).

Back in the mid-90's – a time when browsers had little to no CSS support – icons were managed with the classic <img> tag. This technique brought with it a lot of accessibility and semantic issues. Furthermore, pages that used lots of icons had to fire off a barrage of performance-crushing HTTP requests: one for each icon in the page.

What’s more, if you intended to introduce a :hover effect, you had to load these secondary images with JavaScript.

Happily, things got significantly better with CSS Sprites (or Image Sprites). This technique consists in arranging all icons in a single, unique file (typically GIF or PNG) to be loaded as a CSS background image. The needed portion of the image can be shown by adjusting the background-position property, as in the scheme below (I've also made a pen, if you want to see a running example):

CSS Sprites example

This technique is still used by many huge sites like Youtube and Google and it solved a lot of problems:

  • Only one image file is required, regardless of how many icons you have (including :hover effects), so HTTP requests can be significantly reduced.
  • Many accessibility (and semantic) issues are resolved, since background images and CSS pseudo elements are invisible to text browser or screen reader (while images are content).

I've prepared a little test that creates two lists: one with sprite icons and one using <img> tags. On the left side of the image below, you can see how the two lists are close to identical (except that the second one required much more code).

The right side is a screenshot of the same lists rendered with Lynx viewer (a web emulator of the text-only web browser Lynx) and it can give you some idea of how your web page may appear using assistive technologies (though A.T. output can vary widely).

You can see that the second list containing the images alt texts (green highlighted), which in this case are perfectly useless, since they confuse the content rather than adding meaning to it. True, we can avoid this by using empty alt attributes (as in the last two items), but we still have content elements (the images) being used as presentational attributes.

Lynx Text Browser

Of course, there are many cases which require meaningful icons, and the above CSS sprites example doesn't represent the best solution. We'll come back to this topic later.

Icon Fonts

Although they represented a big step forward, CSS sprites are still bitmap images. As such, if you need to represent the same glyph in different colors or resolutions, you need a different images for each version.

This problem was resolved by font icons: since fonts are vectors, they are resolution independent and can be easily colored through CSS.

The most common way to apply icon fonts to a page is through a pseudo element – just like we did with CSS sprites. Unfortunately this doesn't resolve the issue of meaningful icons, since this technique still leaves them invisible to screen readers.

Let's look at the example below (using Erik Flowers's Weather Icons): Meaningful Icon

The first part of the screenshot represents a common icon implementation (using a pseudo element). In this case the icon is part of the content and has a very specific meaning. Unfortunately Lynx can't see the icon, producing a nonsense sentence. You can see the result in the second part of the image.

Luckily there is an easy workaround for this issue: you can add a description inside the icon element (in this case an <i> tag). The description is wrapped inside a <span> that is styled to make its content invisible to browsers (it has usually a big text-indent value), but not to screen readers, that don't take care about this tricks:

The icon
<i class="wi wi-umbrella">
    <span class="sr-only">"umbrella"</span>
means that it's raining

Now, a screenreader can make sense of this as a meaningful sentence: Meaningful Icons

These topics are deeply addressed in some old articles on Filament Group blog, 24 Ways and CSS Tricks.


More on Accessibility

Although accessibility issues regarding icons are not yet solved, you can do more using WAI-ARIA techniques, paying attention to font sizing, color contrast and so on (if you are interested in these arguments, take a look at the Web Content Accessibility Guidelines from W3C).

But accessibility is not only an issue of screen readers. Even users of common browsers can be seriously impacted by our icon choices. Alex highlighted on SitePoint recently referencing a talk by Seren Davies. It demonstrates how icon fonts are not an evergreen solution, and that it may well be time to move on.

Browsers have wonderful systems for receiving, scaling, rendering and manipulating text. Ultimately co-opting that system to manage and render imagery can only undermine that powerful text function.

The Case for SVG

Finally, we come to SVG.

SVG further enhances what we have seen regarding icon fonts. Chris Coyer wrote an interesting article about Icon Fonts VS SVG features, so I'm going to be very concise about these topics:

  • both are vector-based, so you don't have to deal with resolution issues or multiple files
  • both of them can be arranged and styled through CSS, but inline SVG allows you to control individual part of a single icon, giving you the option of multicolor icons (there are some multicolor solutions for icon fonts too, like Forecast Font or the one described in this Pixel Ambacht article. Nevertheless all them are much more complicated compared to SVG). Furthermore, with SVG you have access to glyphs strokes.
  • the workarounds we need to improve icon font accessibility are not necessary with SVG files, since they have built-in semantically-sensible elements (i.e. <title> and <desc>), not unlike the HTML page itself.
  • Inline SVG can't be cached and reused like icon font, but you can cache external SVG files, as you can with any image file.
  • Icon fonts browser support is complicated but very comprehensive (including IE6+), while SVG requires at least IE9+. Explorer doesn't support external SVG files, but there is a polyfill for this.

SVG icons can be implemented in many ways (I have covered many techniques in my previous SVG icons article), all them can be useful, but I think that the better solution is represented by the SVG symbols technique.

SVG symbols give you the best control on your icons as you can easily change their color and, by using relative units, you can resize them according to the related text.

See the Pen SVG example by Massimo Cassandro (@massimo-cassandro) on CodePen.

At the moment only Firefox seems to let you edit symbol parts via CSS. Viewing the previous pen using FF, the third row should appears just like the last one, which uses inline SVG.

In the same way, text and screen reader support can't be always granted (for example, the previous pen is not correctly rendered with Lynx Viewer).

If you want to see more example, take a look at my other pens about SVG, and if you want to go deeper with SVG and accessibility read Léonie Watson’s very interesting Tips for Creating Accessible SVG or Dudley Storey’s Making SVG Accessible article.


Let's go back to the question we have started from: what is the best choice now between icon fonts and SVG?

As usual, the answer is: it depends. You must consider all the element of your project evaluating compatibility, accessibility, user experience etc. Personally, I'm increasing the use of SVG symbols in my projects, and avoiding icon fonts when it's possible.

Thanks for reading.

  • Up for Font !

  • Peter Weil

    Very good article. Except… there is no such thing as an icon tag in HTML5. The bootstrap people made it up. But it’s unnecessary. If you care at all about semantics, I suggest using something else.

  • cyborgspider

    I was on the SVG bandwagon for my current project at work, using the USE element to reference my icons like a sprite sheet. But then came the need for IE8 support, polyfills for browsers that don’t support USE, and then the realization that using the USE element across a CDN networks violates cross-domain security policies. So back to the font we went. In theory it sounded so nice but in practice, on a large scale project with millions of users where we can’t just design for modern browsers, the safe bet was always a custom web font.

  • Although interesting, the issue you describe is a bit hard to believe. Why would icons disappear on high contrast? Unless there’s a feature on the system you’re using or testing on, the icons should be visible under any color scheme. Additionally, not sure if this problem is an edge case. A demo would be helpful too.

  • Alex, what isn’t a hack these days? :)

    SVG is awesome, but we have to hack left and right to make them work across browsers, no matter the method you use.

    Floats are a hack for layout, but we still use it. Flexbox works very well… on browsers that love it.

    Icon fonts, well yeah they look like a hack (I’m not 100% ready to accept it yet :p) but them little critters work well across OS’s and browsers.

    sIFR… ef’ me. I remember making that thing work… the hacks of hacks of hacks, G damn man! lol. Good ol’ memories :)

  • Massimo, this is one awesome article, Thanks for sharing this information.

    And indeed, the answer is spot on. Today, I haven’t yet dropped icon fonts entirely. On the things I’ve worked lately I’ve used SVGs effectively.

    I personally don’t care if someone uses SVGs or icon fonts or whatever as long as they know what they’re doing. And why.

  • I’ve come to believe custom icon fonts are the best solution, they’re efficient, quick to use and their primary shortcoming – having to be single-colored – is actually more of a non-problem. I really liked inline SVGs until I had many of them, so they may be a good idea in some cases, especially since they’re so easy to edit.

  • I had no idea about this issue, huge Thanks for sharing this.

    Indeed, I noticed the CSS background images gone when using HCM.

    But it kind of is what I initially said: It’s a feature of the system, not necessarily a problem of background images per se.

    Thanks again.

    • Iza Bartosiewicz

      Thanks for being curious :-)

  • Benji Greig

    Good article, my here’s my 2c worth of experience building a few complex web apps:

    Currently I’m erring on the side of font based icons for only two reasons:

    1. They perform better when there are many on the page (iPads and some phones really chug with lots of small inline SVGs).

    2. Ligatures make accessibility a breeze. But your icon font’s of course need to support them.

    That’s not to say that when animation or colour is called for that we can’t swap out a font based icon for an SVG. Just using them more sparingly.

    • Hi Benji
      there are actually many reasons that make icon fonts the better solution in some situation (mainly for some browsers issues). Anyway I always try to use first SVG symbols, since I think they will become the definitive solution.

      Thanks for your comment

      • Colin

        Can I ask why people think colouring icon fonts is not available? I am sure I’ve done it a whole bunch of times as it is just a font…

  • Neil Osman

    On the other hand, when a user wish to enforce his personal css stylesheet, he might override the author [icon]font-family ….

  • twMat


  • fsidc

    I have tried following your guides for creating the SVG (sprites). I created them manually but they always mess up. Ie: things like the svg and use elements are different sizes. They don’t seem to listen to edits made in the CSS panels. Only parts of them showing. Do you have any guidelines for how the SVG’s should be saved before being grouped together? I took an SVG from your CodePen and tried it and it’s fine. But my own and ones downloaded from “onlinewebfonts” all seem to go horribly wrong.
    SVG Download Website :
    Thanks, Neil

  • I just tried creating a branch on my webpack project to switch to use svg icons in place of fonts. I chose to use svg-icon (which added a hella lot of dependencies into the project) .

    However, there’s no “easy” way to refer to them.

    fonts from Material design and Font-awesome were readily available from CDNs so it was just a matter of linking to them in the beginning and I’d have the whole font set (which wasn’t really something I wanted)

    I did this branch to see if I can reduce the load on my project by not using a whole icon font library and instead use a packed subset of SVG icons.

    I went to the point of introducing ReactJS to my project to see if I can create a custom “Icon” tag but in the end this felt excessively hacky and didn’t introduce much benefits.

    It’s still a limitation on the available tooling.

    I think what I need is some sort of svg icon packager that works with webpack that would create a unified svg file that I can refer to like

    • Another thing I had noticed, perhaps someone had better luck… icon fonts take the color and size of the existing font making it more seamless assuming it is part of the text.

      SVGs may default to “black” and have their own size that we have to “adjust” to fit into the text.

Get the latest in Design, once a week, for free.