HTMLBOY Javier Usobiaga, web designer & front-end developer.

How I deal with icon fonts

Using a custom font for icons might look like a hack, because it basically means using typography (intended to show text) to show icons (illustrations). Well, it’s a hack, but an old one: it’s been used for a long time in the operating systems with the dingbat fonts, providing nice vector symbol sets for every text editor around. The fact that the @font-face support is quite spread (Microsoft introduced it back in IE4), the sprite-like behaviour of the font file, the vector nature of the font (and it’s implications with retina displays), the possibility to apply CSS text styles to the icons and tools like Icomoon have made this technique really popular.

A hack is a hack

But still, due to the nature of the web (information that can be accessed with styles, images or JavaScript stripped), this hack can cause an accessibility issue in the browsers that don’t support @font-face, like Opera Mini. This proxy-based browser in particular tries to strip any non-essential information (and font files usually are) to give the user access to information at a lower cost in time and bandwidth.

This kind of issue is not an accessibility problem when the icons are followed by a text label, but can be a real problem in icon-only based navigation (the famous hamburguer menu icon), and also for screen readers.

A simple text fallback

There are several workarounds, some of them avoiding font icons in favour of SVG/PNG sprites (like the famous Grunticon), and I think that they are great tools. But if for some reason (weight, performance…) you prefer to stick to icon fonts, you can serve a span with plain text and hide it only if Modernizr tells you there’s @font-face support.

HTML

<a href="#navigation" class="icon-only">
  <i data-icon="&#xe002;" aria-hidden="true"></i>
  <span>Sections</span>
</a>

CSS

@font-face {
    font-family: 'icomoon';
    src: url('icomoon.woff') format('woff'),
    url('icomoon.ttf') format('truetype');
    font-weight: normal;
    font-style: normal;
}
[data-icon]:before {
    font-family: 'icomoon';
    content: attr(data-icon);
    speak: none;
    font-weight: normal;
    -webkit-font-smoothing: antialiased;
}
.fontface .icon-only span{
    display: inline-block;
    width: 0;
    height: 0;
    line-height: 0;
    overflow: hidden;
}

While this is usually an acceptable workaround, using private areas of Unicode (blank/no-matching letters characters) might provoke compatibility issues in IE8, so if you want to give a text-based support to this browser (and olders), hide the icon styles in a media query:

@media screen and (min-width:1px){
    /* Icon stuff */
}

This is the result when browsing a website with @font-face support:

A browser with icon fonts enabled

And the result when browsing the same site with Opera Mini:

A browser with icon fonts disabled, showing alternative text

To be honest, this is an ugly solution to the font icons problem. But considering that most of the browsers that don’t support @font-face is either because they are old (and usually less capable) or they are sacrificing decoration in favour of a faster access to information, it might be just right for what we are trying to achieve: accessible websites.