Quick Tip: Ever Thought About Using @Font-face for Icons?

Quick Tip: Ever Thought About Using @Font-face for Icons?

Tutorial Details
  • Technology: CSS
  • Estimated Completion Time: 15 Minutes
  • Difficulty: Beginner
Share

The evolution of Internet technologies never ceases to amaze. Seemingly daily, new concepts and techniques are being thought up by creative and talented people. With modern browsers being adopted at a greater rate, systems like CSS3 are becoming more and more viable for use on projects of all sizes. Clearly, this can be seen by looking at new services sprouting on-line like TypeKit. Conceptually, if we deconstruct a font down to it’s basic elements, we can make use of this technology for things other than type, icons.


The Need for Speed

For a short period of time, developers began producing websites with little regard for bandwidth consumption. HTML and CSS where restrictive and Adobe Flash was an open canvas for designers and developers to stuff animations and complex layouts into. This resulted in some extremely bandwidth heavy sites—we all remember a few. Those were the days before the proliferation of mobile smart phones.

With smart phones accessing the Internet more frequently, bandwidth and page load speeds have suddenly returned to the forefront. Thankfully, advances in HTML, CSS, and JavaScript have made that all possible. Central to webpage speed and responsiveness is the number of HTTP requests a page load must make. Modern browsers limit the number of requests to a single server. The W3C HTTP 1.1 specification reads

“A single-user client SHOULD NOT maintain more than 2 connections with any server or proxy. A proxy SHOULD use up to 2*N connections to another server or proxy, where N is the number of simultaneously active users. These guidelines are intended to improve HTTP response times and avoid congestion.”

One technique that has become increasingly popular is the use of CSS sprites. CSS sprites are designed to reduce the number of HTTP requests to the web server by combining many smaller images into a single larger image and defining a block level CSS element to only show a defined portion of the larger image. The technique is simple, but ingenious.


Deconstructing the Font

Fonts at their most basic molecular level are a series of vector glyphs packaged up into a single “glyph archive”.

CSS3 has introduced to the web development world the ability to embed fonts with the @face-face declaration. Without question, this advancement in Internet technologies is one of the most exciting and important stages in our brief history. With developers able to embed fonts of their choice, designers can produce layouts that will render far more consistently from platform to platform bringing the art of interactive layout closer to it’s print cousin.

If we take a closer look at the technology behind a font, we can gain a far better understanding of how they can be used and deployed. Fonts at their most basic molecular level are a series of vector glyphs packaged up into a single “glyph archive”. We can then reference each glyph by its corresponding character code. Theoretically, it’s very similar to the way in which we reference an array in almost any programming language—through a key/value pair.

With this in mind, the glyphs we reference can really be any vector-based single color image. This is nothing new—we’ve all seen Dingbats and Webdings. They are two examples of non-type fonts, that is, a series of vector based images compiled into a single font archive.


Abstracting and Expanding @font-face

With the advent of font embedding and the realization that fonts are essentially a series of simple vector glyphs, I began to experiment on how to use this format to my advantage. Conceptually, if I placed all required icons for a particular site into a custom font, I would then be able to use those icons anywhere on the site with the ability to change size and color, add backgrounds, shadows and rotation, and just about anything else CSS will allow for text. The added advantage being a single CSS sprite-like HTTP request.

To illustrate, I’ve compiled a new font with a few of the great icons from Brightmix.

Sample glyph chart

I’ve used the lower case slots for plain icons, and the uppercase slots for the same icon in a circular treatment.

To use my new Icon Pack, I’ll first have to export my font set as a number of different font files (.eot, .woff, .ttf, .svg) to be compatible with all browsers. The topic of font embedding and file format converting is covered elsewhere, so I will avoid a detailed explanation here. However, the CSS would look something like this.


@font-face {
  font-family: 'IconPack';
  src: url('iconpack.eot');
  src: local('IconPack'),
    url('iconpack.woff') format('woff'),
    url('iconpack.ttf') format('truetype'),
    url('iconpack.svg#IconPack') format('svg');
}

Once embedded, I now have a complete icon set in vector format to reference. To reference an icon I simply need a style that includes the font-family of “IconPack”.

XEROX CODE

<style>
.staricon {
  font-family: 'IconPack';
}
</style>

<div class="staricon">a</div>

The above example would render a star and is the most basic use of the Icon Pack concept, however it’s not very intuative from a development perspective, not SEO friendly, nor does it gracefully degrade in the case of non-CSS support.

To remedy the situation, I’m going to include a :before pseudo-element and wrap the content in a span tag.


<style>
.staricon {
  font-family: 'IconPack';
}
.staricon:before {
  content: 'a';
}
.show {
  display:block;
}
.hide {
  display:none;
}
</style>

<div class="staricon">
  <span class="show">star</span>
</div>

Now, the star is added to the display and I can toggle the visiblility of the text by using the show and hide classes. The result is an easy to reference CSS class that degrades gracefully and is optimized for search engines. For my entire set of icons, I can write something like below.


<style>
.show {
  display:block;
}
.hide {
  display:none;
}
.icon {
  font-family: 'IconPack';
}
.star:before {
  content: 'a';
}
.rss:before {
  content: 'b';
}
.screen:before {
  content: 'c';
}
.talkbubble:before {
  content: 'd';
}
<!--
... and so on ...
-->
</style>

<div class="icon screen">
  <span class="hide">screen icon</span>
</div>

Icon Pack Usage

The benefit here is that the icon will scale with the font size. In fact, all icons will scale and maintain perfect clarity.

So far, we’ve only touched the tip of the iceberg, nothing groundbreaking here, although you may start to see the possibilities. A real world scenerio would be the replacement of the list-item-style. As apposed to using an image, we can now use a vector icon from our Icon Pack. The benefit here is that the icon will scale with the font size. In fact, all icons will scale and maintain perfect clarity.

Since the icons are now placed on our page as if they were text, we can apply any valid CSS style to them without downloading any other assets. We could apply color, font-size, text-shadow, etc and make use of the :hover pseudo-element for mouse over effects—all with a single glyph.

As with anything, there are some unfortunate limitations. As of this writing, there is no way to display a single glyph with multiple colors. There has been some CSS trickery to get gradients over live text, however complex shapes with varying colors in a single glyph is a limitation. Having said that, there are ways to approximate multi-colored glyphs by segragating the parts of a vector graphic into individual glyphs then assembling and coloring them on the page through CSS.

Another interesting usage is a simple CAPTCHA validation. By replacing the glyphs for the alphabet with numbers, users will see numbers, but the page code will be letters. Some simple computation to translate between the two, and you have an easy to read CAPTCHA.

To better illustrate these concepts, I’ve assembled a sample page made up of two HTTP requests—the page code and a single Icon Pack. Included as well is the ability to scale the font size of the page to clearly demonstrate the flexibility of embedding vector glyphs. The company logo, navigation, imagery, and CAPTCHA are all using glyphs. Please note, the CAPTCHA included here is for illustration only. To use this on a production site, I would recommend validating on the server side with a dynamic algorithm as apposed to JavaScript.

This sample page also demostrates the use of a glyph as a scalable “repeating” background. I’ll be the first to admit this implementation is hack-ish at best, however I think it demonstrates the flexibility and versatility of the Icon Pack.

Clearly, this opens up some possiblities. Designers can develop Icon Packs for sale, corporate entities can host a single Icon Pack to be used on all corporate media. Template designers can easily distribute multiple color options of the same template all without having to save and export a single extra file. Web designers can easily scale existing sites to be compatible with hand held devices. Furthermore, this technique exposes our icons to the DOM enabling animated Flash-like effects with your favourite JavaScript API.

As usage and browser support for CSS3 penetrates further, Icon Packs will soon have a large impact on content delivery furthering the light weight, scalable, multi-device trends that are starting to become a necessity.

Related Posts

Add Comment

Discussion 113 Comments

Comment Page 2 of 2 1 2
  1. Was not aware of this, thanks for the tip.

  2. Armin says:

    AWESOME! It’s one of those “why didn’t I think of it!” ideas.

  3. Alvin says:

    Interesting article, but I don’t think iPhones support @font-face. Not sure about Android or other mobile platforms, but thought it was worth bringing it up since you mention smart-phones in your intro.

  4. Ed at Kliky says:

    Interesting approach. Anything that can be done, should at least be attempted. Pushing forward.

  5. erickaweb says:

    Would you mind writing the next tutorial on how to create your own custom font and compile it please?

    Thanks!

  6. Really clever idea, Wayne.

    I’m happy to see you’re using the content attribute, too. When I first read the title, my first thought was “un-semantic blasphemy!”

  7. WebGuide4U says:

    thanks for the share. was not aware of it.

  8. Robby says:

    Nice idea but on IE8 we have to wait a moment for the font-facve/cufon/other font trick to load and so we see ‘c’, ‘g’ etc before they miraculously turn into icons.

  9. _freshface says:

    Very good idea, but I prefer making icons on my own as jpegs or pngs.

  10. Fireball70 says:

    Sorry but this example is absolutely unusable till IE6-7 still alive…

  11. Phil says:

    Never thought of this, but once i’ve read it I got that nasty feeling of someone screaming “DUUUUUH!” in my ear.
    Thanks a lot ! :)

  12. I did notice a slight problem with rendering when a browser doesn’t use cleartype by default. The edges are rugged, however. When you hover and a color is changed, the edges flow with AA… So I think there are still some issues with this solution.

    I do see a great potential to speed up web-apps, though I recommend to only use it with >24px size icons, to prevent the icons from breaking.

    I like the idea, very much… Good luck exploring the possibilities :)

  13. MarcoBarbosa says:

    It all comes down to IE.

    So it’s a great idea yes, but we might have to wait a liiiitle bit.

  14. HotCustard says:

    Very clever and not something that had occured to me before. Not sure if ill make much use of it, but nice experiment all the same.

  15. Andy Kempson says:

    Genius! So simple when presented like this and something I will certainly be implementing in future! Thanks!

  16. Merlin Mason says:

    Thanks for sharing this… An interesting way of using the existing technology.

    Taking the idea further, I’m wondering how feasible it would be to slice a logo, turn it into a font using the appropriate characters of the brand name, arrange the glyphs with zero tracking and be able to type it straight into an H1 tag. In theory this should be more SEO effective than a jpeg with an alt tag, I think?

    Quite do-able with a simple logo such as IBMs… But would require perfect cross browser rendering for something like the Nike swoosh for example.

    Also becomes problematic if you have repeat characters.

    Just a thought!

  17. Chad Pierce says:

    I love the pseudo classes. the one thing ‘bug’ that I noticed is if I refresh the page using F5 the fontface effect disappears. really odd. it took me by surprise but when i reload the page by using the refresh button it comes back. I dunno. I cant wait till all browsers are compliant 100%.

  18. Duncan says:

    Interesting hack. Would certainly help with page zoom, character alignment, sprites, etc… but only at a small size. There’ll be issues with rendering on non-cleartype browsers, plus @font-face isn’t ‘official’ yet.

    But I like the possibility…

  19. Rob says:

    Theres an issue here. If the browser doesnt support @font-face then the user sees a letter. Surely this isnt semantically correct.

    Internet explorer is fine with @font-face down to version 5 in case there was some confusion.

    Check out http://www.font-face.com for more details on their new service.

    • Anonymous says:

      They’d be more likely to see “screen icon” or “save icon” — at least if you used the “complete” version that includes :after. It’s possible they’d see a letter, if the browser supports :after but not @font-face. But I think that’s a very slim segment of the browser market.

  20. Nuruzzaman Sheikh says:

    Knew to use @font-face but not the way you showed here. Thanx

  21. So it’s a great idea yes, but we might have to wait a liiiitle bit.

  22. Rhyaniwyn says:

    Aside from the not-quite-all-there support and sacrifices for so many older browsers & platforms, remember this http://webaim.org/blog/hiding-content-for-screen-readers/ for when you want to hide things accessibly.

    To some other commenters, if you look further down the post you’ll see a solution that degrades rather gracefully.

    Of course this doesn’t work in all browsers all the time perfectly — it’s a new technique. But it has great advantages for bandwidth and modularity, etc.

  23. Youhou ! Great tip, i never thought to use font-face like this.

  24. Hey, once again a really informative tutorial! I was wondering what are the restrictions to using @font-face in browsers? Do all browsers support this particular bit of CSS3? This seems to be a better replacement for using special .fonts for headings etc instead of using sIFR or Cufon.

    Warren Jerzyszek

  25. Adrian says:

    This is a good idea, for single color icons. If you allow users to customize their theme the icons can easily be changed with font-color and the icons take advantage of subpixel font smoothing. Unfortunately if you need multi colored icons you’re out of luck…

  26. Useful and innovative technique. Thanks for sharing.

  27. Luke says:

    How did you create the font? what software did you use?

    Thanks!

  28. Thanks for the great post !
    I will use this method for the icons I’ll add to my new site !
    I wouldn’t ever come to such an idea.

    Great!

  29. Wayne Helman says:

    It has come to my attention that the JavaScript file was never included in either the demo nor the source files. You can have a look at a proper working demo here:

    http://www.fiftyonereasons.com/examples/iconpack/index.html

    and download the source here:

    http://www.fiftyonereasons.com/examples/iconpack/iconpack.zip

    Cheers!

  30. GeekNoise says:

    Hi, i’m using this for displaying opensource logos on my website : http://geeknoise.com/

    but we must wait before the font loads !

    how can i fix that ?

    Thank’s

    • Wayne Helman says:

      Looks great! However….

      You’re using it slightly incorrectly. Don’t directly insert the reference character into your HTML code. I see the site already has HTML5 features, so better to use the :before or :after pseudo elements. That way, it becomes SEO friendly – see the third code snippet in the article.

      For loading delays, I have found the best way to render @font-face fonts (or Cufon for that matter) is to set the opacity to 0. Then, using you’re favourite JavaScript API, bring up the opacity to 1 after the page has loaded.

      Tweet me @BrandedHead if you need more info.

  31. Nice idea. You could get crazy with CSS3 text-shadows and whatnots.

  32. Jeremy says:

    I’m glad this is coming back. Using Webdings in IE4/5/6 was fantastic back in the day.

  33. Ivor says:

    Forget it, use jpg/gif/png sprites.

  34. Maarten says:

    What I was wondering about is the amount of HTTP request that should be made to all those font files. Or will the browser just pick one that suits him best?

  35. Dragon says:

    OK. I am using FF 3.6. Some fonts show up and other do not – like “wingdings”. Triple checked the syntax. Everything is correct. Is there a reason why some fonts would not show up and others do? Would some sort of copy write protection prevent a font from showing up? Thanks.

Comment Page 2 of 2 1 2

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.