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
This entry is part 11 of 16 in the CSS3 Mastery Session
« PreviousNext »

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”.


<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.

Add Comment

Discussion 121 Comments

Comment Page 1 of 21 2
  1. Benn Wolfe says:

    What an awesome article. This is very clever and could really make a big difference in my projects. Thank you.

    • abhishek says:

      Hi,
      I am trying to make a theme for my blog with zero image. I am sure this is gonna help me for social media icons and othr icons.
      Thanks for this article..

  2. insic says:

    Brilliant Idea!

  3. Arik says:

    I prefer using Base64 images when it comes to very small iconography. Of course given that it’s consistent. The base64 is simply added to the css and that’s it.

  4. Adri says:

    Nice!

    Thanks!

    I will look it ;)!

  5. Robert says:

    Nice idea! I’ll try that out right now :)

  6. Great approach with @font-face. Excellent example and tutorial. Really love it!

  7. Shaun says:

    I’m impressed…

  8. Huckleberry says:

    Great tut. I work alot in both print & web, and this idea is certainly born from print. Excellent idea on executing it on the web.

    However, how will search engines react to this?
    Say I have a logo as that’s a font glyph from Zapf Dingbats, will search engines display the glyph, the key used to make the glyph—such as K—or an annoying question mark in a diamond?

    That’s the only downside I can think to this method currently.
    Huck.

  9. Marcy says:

    Fascinating idea.

    How do you “compile a new font”?

  10. Excellent idea Wayne. I never even thought of doing that. I see this idea being further developed in the future. Nettuts is awesome!

  11. Dave says:

    Very creative! With the impetus of your recent font-face tutorials egging me on, I’ve already implemented font-face for text on two client sites.

    I never would have thought of this, though. Obviously we’re all used to using images for icons, but the idea of resizing and recoloring them is very cool. I hope to use this sometime!

    Thanks.

  12. Sean O says:

    Interesting effect, but yet another not-ready-for-production “technology preview” if you’re simply ignoring IE.

    • Rob says:

      @font-face was originally introduced in CSS2; and has been supported by Internet Explorer since version 4. The only catch is that IE only supports EOT (Embedded OpenType). I’m not sure if this has changed in any recent version of IE.

    • Paul Irish says:

      Um? Like Rob said, this has been in IE since ie4. The code here works just fine.

      IE4-IE8 support .eot format. It’s likely IE9 will support both eot and WOFF.

    • Anna says:

      The reason this isn’t ready for IE is because IE6 and 7 don’t support the ‘content’ property in CSS.

      The only way to make it work in IE6-7 is to actually write the letter out in the html, which leaves stray letters all over the place, or use Javascript to document.write everything in, but if Javascript isn’t enabled, your user doesn’t see the ‘images’

  13. Matt Ward says:

    This is a remarkably clever idea, with lot of upside potential. I think of something like this very TUTS+ network, and how a single custom font like you describe could be used to create simple icons that can be applied across an entire network of similar sites. Changing the colour from site to site would be a simple matter of a few lines of CSS, rather than having to create and host different coloured images for each circumstance.

    I really like this idea, and may consider it for an upcoming project!

  14. Interesting idea, but I’m quite unsure if it’s really practical in the wild. Accessibility, SEO and load times issues come to mind. Is it really better to load a whole font file that might be 30-100kbs in size or just one sprite image file that’s around 15-30kbs? What if the stylesheet, for whatever reason, doesn’t load? What about screenreaders? Search engines? All they’ll read is a letter with no real meaning to them.

    Matter of testing, I guess.

  15. Evert says:

    Hey, great tip! I didn’t know this was possible at all! Thanks.

  16. Patrick says:

    Ouh damn, you’re right. This is a brilliant idea.

    And you don’t really need CSS3, how about “cufon”?

    http://cufon.shoqolate.com/generate/

  17. Gabri says:

    I made something like this when i was designing my Portfolio but i made in the 404 page http://www.gabri.me/404 “hover over it ;)” and it`s working everywhere even in IE6 .

    i used http://www.fontsquirrel.com/fontface/generator

  18. JohnONolan says:

    That is very clever indeed, a really neat idea :) I do share the concerns of other with regards to search engines and screen readers though, it isn’t very semantic!

  19. StoicMania says:

    Frequent NetTuts/TutsPlus follower and web design hobbyist. I’ve finally found a compelling reason to add a comment!

    I was actually talking about this a few weeks ago with a friend who’s more into computer programming, but who understands the basics and keeps up to date (mostly due to my efforts to pull him in hands-and-feet). Glad to see I’m on the same line of thought as others! I’d like to see how this might be applied and how long it takes for it to catch on, if it does.

  20. Juan C Rois says:

    This is very clever, I’ve used dingbats and webdings in my designs before, but never thought of it as part of a Font Face kit.
    I’m impressed and very interested to use this in the real world.
    Thanks

  21. Senichiro says:

    Wow, i think i’m going to use it. Thanks. :)

  22. Alex Flueras says:

    Awesome article. Haven’t thought about this possibility… Thanks for sharing!

  23. Xcellence IT says:

    Nice Idea… would like to try this….

    Can you please explain what is woff & svg file type? And how can we build a custom font ttf and all?

  24. Charles says:

    Very slick indeed. Website owners/devs should be concerned with speed, especially since G announced that they may factor page load times into rankings. Besides, more and more people are using lower bandwidth connections like 3G cell phones to surf.

  25. Fynn says:

    Nice idea & article.. but am I the only one who thinks @font-face rendering is just to awfull to put in your site? I still prefer Cufon.

  26. krike says:

    wow great tip, never thought of using font face like that :D thanks

  27. Wayne Helman says:
    Author

    In response to the few concerns about SEO and screen readers, the concept here is to remove the glyph designation from the HTML and define it in the CSS with a :before or :after pseudo declaration. This first example is specifically NOT SEO friendly and a solution is presented that eliminates the issue. In fact, I believe SEO could be enhanced.

    Take the example of the logo in the example files. This could easily be written like this:

    The number one thimble manufacturer worldwide
    123 Street Avenue, Toronto Ontario

    1-800-999-9999
    All thumbs? We got you covered.

    Company Ltd.

    • Wayne Helman says:
      Author

      sorry, html got stripped.

      <div id=”logo”>
      <div id=”mark”>
      <ul>
      <li id=”tl”><span class=”hide desc”>The number one thimble manufacturer worldwide</span></li>
      <li id=”tr”><span class=”hide address”>123 Street Avenue, Toronto Ontario</span></li>
      </ul>
      <ul>
      <li id=”bl”><span class=”hide tollfree”>1-800-999-9999</span></li>
      <li id=”br”><span class=”hide byline”>All thumbs? We got you covered.</span></li>
      </ul>
      </div>
      <div id=”wordmark”>Company Ltd.</div>
      </div>

  28. Frank says:

    Great idea. Could you create a custom font for http://www.iconsweets.com/ , please? I would like to use it’s icons for social media services for my current project, and this would be a great chance to enhance performance.

  29. Execllent idea, I will definitely use it too !

  30. Anjum says:

    Hey

    In demo or theory the idea is very good. Right now i am on firefox 3.6.3 and to be honest with you my browser isn’t rendering it very clear and crispy. after all it has to look nice. for this reason i can’t use such technique on live/clients site I would go with css sprint…

    Thanks

  31. Excellent article / technique.

    Took me some time to puzzle it all out from the demo because the .content property in the CSS doesn’t show up in Firebug’s style inspector pane (at least not for me … I’m probably doing something wrong, no doubt).

    The .content properties are visible if one clicks on the CSS tab in Firebug, of course.

    Once I figured out that the letters a, b, c, etc., were the letters corresponding to the “lowercase” versions of the icons, and the A, B, C, etc., corresponded to the circular “uppercase” versions of the icons, it all fell into place.

    One of the great advantages of living under a rock is that I frequently get to enjoy these ah-ha moments when reading Nettuts articles :)

  32. Matt Bridges says:

    This is a fantastic idea! Rather than having to use multiple images (or a sprite) for icon sizes, using a font would make the scaling process a breeze! Well done! I love it!

  33. Lukas says:

    Wow, why didn’t I think of that? :)
    Just too bad there isn’t a way to use multiple colors in the ‘icons’.

  34. Now that is a good idea if I ever saw one!

  35. For the screenreader – beside putting them into :after and :before –
    there are a few Slots in Unicode allready for Symbols and the like
    http://en.wikipedia.org/wiki/Miscellaneous_Symbols and http://en.wikipedia.org/wiki/Dingbat
    There is also an overview http://en.wikipedia.org/wiki/List_of_Unicode_characters

    If that is not sufficient there are private use ranges in Unicode:
    F0000..FFFFF; Supplementary Private Use Area-A
    100000..10FFFF; Supplementary Private Use Area-B
    which means if you put your symbols within this Unicode ranges they simply won’t have a meaning for the sreenreaders.

  36. Awesome !
    never thought of it earlier
    wil sure try it out in my next project

  37. BORA says:

    No, I never thought about that :D
    Interesting approach!
    Thanks!

  38. Zen Savona says:

    Actually its interesting you wrote an article about this, because ive been using it for a while, not for the kind of icons you are using it for, but for things like arrows and buttons. the only problem is that when converting to a font you lose any color (for non-solid color icons).

    To answer the question posed by alot of people, a newsreader will just show the letter you have used as an alias for the icon. which is less than desirable. but it does not cause any problem if using these icons in your layout, for example RSS icons and such.

    I’m really glad to see someone else thought of this and putting this great idea to good use.

    Zen

  39. Now, here is a novel idea! One might spruce it up though if Javascript is used to add the nonsensical characters to the right spots, working around the hole “what will google think of it?!” problem without resorting to the pseudo-class trick done here. It can be done fairly easily and simplifies the approach to this technique considerably.

    Just think of what would happen if a new designer got hold of a project that used that technique without knowing about it beforehand. He or she would probably screw all of it unknowingly and would be left asking “what did I do wrong?”. If it was a JS clearly labeled “iconpack.js” included at the head that did the trick the odds of that happening would most certainly drop.

    The reason I’m saying all of this is because it’s been my experience that people who assume other persons CSS don’t read comments, ever. They just start to change it all thinking they “know CSS” and end up destroying such little tricks like this because they just didn’t knew better.

  40. Jayson Brown says:

    Amazing concept Wayne, makes me think about creating my own Fonts!

  41. antony says:

    I’d like to know whether it works for people viewing the website on a Mac or under Linux, thanks.

  42. Yes i did think about that, even wanted to build an entire font for that specific idea. Didn’t get to do that tho.

  43. cuginoAle says:

    Awesome!
    “The topic of font embedding and file format converting is covered elsewhere, so I will avoid a detailed explanation here”
    Can you please post a link?
    How do we convert a vector file to ttf?
    Thanks a lot.

  44. ScaraX says:

    Quite bad if the browser supports CSS3, but no @font-face like on android ;)

  45. rizq says:

    Btw, it doesn’t work in linux ?

  46. Dan says:

    Lovely idea!!
    but as a few people of mentioned, search engines and screen readers concerns..

  47. John Grimes says:

    TypeFront would be ideal for this sort of stuff.

  48. Kaeden says:

    Great idea, However the fact that it doesn’t work in Internet Explorer is sadly the only part that keeps me from using it.

    I took a screenshot of how your demo looked in IE8, http://i40.tinypic.com/2mg1rb9.jpg

    Anyone have any work-arounds that still keeps the page SEO and screenreader friendly without using javascript? would be greatly appreciated.

  49. arnau says:

    *uff* it’s a bizarre idea! What about accessibility? And what about browsers without @font-face support?

Comment Page 1 of 21 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.