Using icons from icon fonts directly in CSS

I've become a huge, huge fan of icon fonts lately, for reasons well enumerated elsewhere.

However, in learning how to use them, I had to rethink how I wrote markup. For years, I've been using background images via CSS for the kinds of visual elements that I now wanted to use an icon font for. That meant actually inserting HTML elements for the icons - and not relying on CSS alone. I would need to insert something like:

<span aria-hidden="true" data-icon="&#xe014;"></span>

That means more verbose markup, but is something I can live with.

The bummer is when you're in a situation where inserting new markup is either impossible or at least very painful. I'm thinking of things like manipulating the menu markup generated by a CMS (e.g. it can be a royal pain in Drupal).

What I discovered is that you can insert an icon, using an icon font, purely in CSS. It just takes a little advanced CSS and a special re-writing of the icon unicode characters for the icon.

Let's say you've already generated your own icon font via a service like IcoMoon.io. Let's also say the font is named "icon-font" or something else. When you download your font, you get an example page with all of the unicode characters that correspond to icons in your font.

The unicode characters look like &#xe002;. When generating a font via something like IcoMoon, these characters will be particular to your own font.

Typical usage for these unicode characters is to insert a span like shown earlier, then to use the data-icon attribute to insert the icon:

[data-icon]:before {
  font-family: icon-font;
  content: attr(data-icon);
  speak: none;
}

But what we are after is not having to touch the markup at all, while still using an icon font.

You can by target a specific element, then use the :before pseudo element, and insert the unicode character that way. It just takes a little tweak to how the character is written to escape the unicode character within CSS.

Let's say you have a link in your navigation to "/about" and you want an icon to go along with that link. In you generated icon font, that icon is mapped to the unicode character &#xe002;. You would then target the link via an href attribute selector:

a[href*="about"]

Then insert the icon via :before -

a[href*="about"]:before {
  content: "\e002";
  font-family: "icon-font";
}

The real trick is simply changing '&#xe002;' to '\e002;' when wanting to use the character directly within your CSS. You can apply whatever other CSS properties that you want to the icon - display, color, font-size, etc.

That same unicode escaping is also useful for targeting existing icon span elements. Let's say we have the same span as before:

<span aria-hidden="true" data-icon="&#xe002;"></span>

We can target that particular icon with this attribute selector:

[data-icon="\e002"] {
  ...;
}

This is most useful when need to slightly tweak an icon's position when it exists in markup.

That's how to include icon font generated icons without touching your HTML. You can also use the same unicode escaping to target existing icons that have been inserted into markup.