Introduction
Using a font to represent an icon has advantages over the traditional method of using an image, namely:
- Scalable - works nicely regardless of client's magnification or view device DPI
- Can change the colour with CSS
- Can do everything traditional icons can (e.g. change opacity, rotation, etc.)
- Can add strokes, gradients, shadows, and etc.
- Convert to text (with ligatures)
- Ligatures are read by screen readers
- Changing icons to fonts is as simple as changing the font-family in CSS
However there are some shortcomings to keep in mind:
- Icon fonts are generally mono tone in colour
- IE8 and IE9 do not support ligatures
- Globally changing fonts will cause the text vs the icon to show
- In situations where there is existing text accompanying an icon, specific markup containers need to be created for the icon
- Modifying icon fonts is as involved as generated a new icon graphic in the "traditional" way - there is no real time saved in that regard
Also see:
Procedure Summary
- Create the icon and save it as an SVG graphic.
- Use IcoMoon to generate a font from an SVG graphic.
- Add the font to your markup. Example:
@font-face { font-family: 'CustomIcons'; src: url('../fonts/CustomIcons.ttf'), url('../fonts/CustomIcons.eot'); } a.myLink-icon { font-family: 'CustomIcons'; } a.myLink-icon:before { content: "\e000"; /* The custom Unicode (aka. PUA) for the icon you want. */ color: #ED3820; /* Custom colour. */ }
Step 1. Creating an SVG Symbol
Use illustration software to create an SVG version of the icon you want to use as a font.
Tips:
- The dimensions of the graphic doesn't matter since everything will be scaled by the browser's font-rendering.
- Work in binary (i.e. black and white) and do not apply effects such as drop-shadows or embossing.
- Sometimes the font conversion of the SVG may not work properly, so be prepared to edit your SVG file again.
- Overlapping regions of shapes may cause a subtraction when converted in IcoMoon (i.e. it will render as transparent) - in this case you may need to build a single shape from these conflicting shapes, or ensure none of your shapes overlap.
Download Example SVG file: pencil-icon-01.svg
Step 2. Using IcoMoon to Generate Font
Steps:
- Go to IcoMoon (you can also run IcoMoon in "offline" mode in Chrome browser by installing the IcoMoon Chrome app)
- Import your SVG icon - select "Import Icons" and choose your SVG file.
- Select your icon from the list (should appear under "Your Custom Icons" section, and select the "Font ->" button at the bottom of the screen.
- Save the ZIP file to a known location.
- Note: selecting the "Preferences" button will give you options to name your CSS classes and files. It is recommended you use identifiers
- Extract the contents of the ZIP file.
- The files we are most interested in are the
./fonts/*.eot
,./fonts/*.ttf
, and the./index.html
files.
- The files we are most interested in are the
- To verify that the font looks proper, open the
./index.html
file in a web browser. If the icon doesn't look right, you may need to edit the SVG file and repeat the font generation process.
Step 3. Working with CSS and HTML
Once you are satisfied with the appearance of your font, it is time to add it to your HTML and CSS markup.
First, add or identify an element in your HTML markup for the new icon.
For example you have the following existing HTML and CSS:
/* Existing HTML markup before adding new icon font. */ <a href="contact.html" id="contact_form">Contact us</a> /*this where the new font icon will go */
/* Existing CSS markup for the HTML before adding new icon font. */ #contact_form { background: url("../images/envelope.png"); /*existing image that will be replaced by icon */ }
Next, add the new font to the CSS markup.
@font-face { font-family: 'CustomIcons'; /*Specify the new font */ src: url('../fonts/CustomIcons.eot?#iefix') format('embedded-opentype'), /* IE8 fix. */ url('../fonts/CustomIcons.ttf'), url('../fonts/CustomIcons.eot'); } #contact_form { background: url("../images/envelope.png"); /*existing image that will be replaced by icon */ font-family: 'CustomIcons'; /*the new font icon */ }
Finally, add the new icon into the BEFORE pseudo class and delete any references to the old icon image.
@font-face { font-family: 'CustomIcons'; /*Specify the new font */ src: url('../fonts/CustomIcons.eot?#iefix') format('embedded-opentype'), /* IE8 fix. */ url('../fonts/CustomIcons.ttf'), url('../fonts/CustomIcons.eot'); } #contact_form { /* old icon image has been removed. */ font-family: 'CustomIcons'; /*the new font icon */ } #contact_form:before { content: "\e000"; /*the custom Unicode (aka. PUA) for the icon.*/ }
This is all that is needed to add the new icon to your markup. You will notice there is a line specific to IE8 - for more information on this, please see http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax.
Unicode for font
The Unicode (or "PUA code") for the custom font can be found in the HTML and CSS file generated by Ico Moon. If the HTML and CSS files are unavailable, you can retrieve the Unicode using one of the methods listed under the section "Dealing with the TTF Unicode" below.
However, there is a problem - the new icon font will replace the existing font of its container and all child elements and therefore removing any font styling you may have wanted to preserve. The next section will outline common issues and how to fix them and some best practices.
Common Issues
Preserving Existing Fonts
In the example above, the new custom icon font was added to an element that has existing text which causes a problem - any other existing custom font will be overwritten within that container.
To illustrate this problem, assume Comic Sans is the font applied to the <body>
element of our example, and an icon font added to the <a>
anchor within the <body>
. Comic Sans will appear throughout the document except for the contents within the <a>
, which means "Contact us" will no longer be Comic Sans.
<body> <a href="contact.html" id="contact_form">Contact us</a> /* "Contact Us" should be in comic sans */ </body>
@font-face { font-family: 'CustomIcons'; src: url('../fonts/CustomIcons.ttf'), url('../fonts/CustomIcons.eot'); } body { font-family: 'Comic Sans MS'; } #contact_form { font-family: 'CustomIcons'; } #contact_form:before { content: "\e000"; }
To overcome this issue, a new separate element should be created in the HTML for the icon font with no other content contained within. The CSS file is then updated to reference this new markup structure.
<body> <span id="#icon-envelope"></span><a href="contact.html" id="contact_form">Contact us</a> /* "Contact Us" should be in comic sans */ </body>
@font-face { font-family: 'CustomIcons'; src: url('../fonts/CustomIcons.ttf'), url('../fonts/CustomIcons.eot'); } body { font-family: 'Comic Sans MS'; } #icon-envelope { font-family: 'CustomIcons'; } #icon-envelope:before { content: "\e000"; }
Images and Labels
It's common for images to be used in functional ways such as acting as a button within an anchor tag. For example:
<a href="download.html><img src="./images/download.png" alt="Download our latest stuff!"></a>
The problem here is if we replace the image in the anchor with an icon font, any text descriptions (the alt text) will be removed as well - causing a possible usability and accessibility issue.
<a href="download.html"></a> /* The alt text is now gone, causing a usability and accessibility problem. */
@font-face { font-family: 'CustomIcons'; src: url('../fonts/CustomIcons.ttf'), url('../fonts/CustomIcons.eot'); } a { font-family: 'CustomIcons'; } a:before { content: "\e001"; }
To bring back some semantics and to help improve accessibility, we use "aria-label" to describe the functionality.
<a href="download.html" aria-label="Download our latest stuff!"></a> /* Aria-label takes the place of alt text. */
Cross-Browser Oddities
Icon fonts can appear different across browsers and across operating systems. For example, the following icon is rendered differently in Firefox in Mac OS X and in Windows despite being the same icon and the same browser.
To avoid these rendering problems, when creating the SVG images avoid using fine details - not only does this help eliminate details in the icon font being lost during rendering, it also helps improve usability through clearer icons.
IE8 Compatibility
To ensure custom fonts get rendered properly in Internet Explorer 8, you will need to add ?#iefix') format('embedded-opentype')
to your CSS. For example:
@font-face { font-family: 'CustomIcons'; /*Specify the new font */ src: url('../fonts/CustomIcons.eot?#iefix') format('embedded-opentype'), /* IE8 fix. */ url('../fonts/CustomIcons.ttf'), url('../fonts/CustomIcons.eot'); }
The IE8 fix needs to be the first URL in the list of sources otherwise the font will not appear.
Reference: http://www.fontspring.com/blog/the-new-bulletproof-font-face-syntax
Dealing with the TTF Unicode
Ico Moon conveniently generates an HTML and CSS file for custom fonts which contain the Unicode to be used in your markup. However, in the scenario the original CSS or HTML files are unavailable, here are two ways to obtain the Unicode on Windows and Mac OS X 10.6+.
Obtaining Unicode in Windows
- Install the custom font (usually a right-click then select "Install" from the context menu).
- Run Character Map (done by searching the Start menu, or by typing Win+R then "charmap").
- Select the custom font from the Font drop-down menu. The glyphs in the custom font should now appear in the window.
- Select a character in the window. The Unicode will appear in the bottom-left corner in the status bar.