Blog

Use a Custom Icon Font similar to how you would use Font Awesome

March 11, 2015    Web

Setup and maintain a custom icon font, and use it like Font Awesome.

Many projects require custom icons at some point, and icon fonts are great for a lot of reasons. However, usually we don't have the luxury of starting our projects with a complete design. Because of this, it can be helpful to start out with an existing, free icon set like Font Awesome.

In this post, I'll show how I recently transitioned a project from using Font Awesome to a custom icon font using Font Custom.

Adding the SVGs to the repository

I prefer to store the SVGs in the project repository, that way the font can be updated and rebuilt at anytime. To do this, I created a directory called app/assets/icon_svgs. I added all of the icons to this directory, and renamed any SVGs that may have had spaces in the name (designers!).

As an example, I'm going to create a diamond icon font, so I've added the following files:

app/assets/icon_svgs/diamond-1.svg
app/assets/icon_svgs/diamond-2.svg
app/assets/icon_svgs/diamond-3.svg

For this example, I used SVGs from iconmonstr. (Thanks!)

Install and Configure Font Custom

Start by following the Font Custom installation instructions on their website.

Because we want anyone to be able to rebuild the icon font at any time, we're going to create a fontcustom.yml file within the app/assets/icon_svgs folder that we created above.

There are a ton of options, but here are the main details:

fontcustom.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
font_name: diamond-icons

# Format of CSS selectors. {{glyph}} is substituted for the glyph name.
css_selector: .diamond-i-{{glyph}}

# Generate fonts without asset-busting hashes.
no_hash: true

# Forces compilation, even if inputs have not changed
force: true

input:
  vectors: app/assets/icon_svgs

output:
  fonts: app/assets/fonts
  css: app/assets/stylesheets

templates:
- scss-rails

preprocessor_path: ""

I'm specifying a custom css selector for our font, beginning with .diamond. I'm pointing the input to our SVG folder, and the output to the fonts folder. Finally, I'm using a built-in Font Custom template for Rails scss, since I'm using Sass.

You can see the full config file in this Gist.

Building the Font

At this point, from the project root, we can call fontcustom compile -c app/assets/icon_svgs/ to build the icon font. Notably, this results in the creation of our font files, as well as our stylesheet.

      create  app/assets/fonts/diamond-icons.ttf
              app/assets/fonts/diamond-icons.svg
              app/assets/fonts/diamond-icons.woff
              app/assets/fonts/diamond-icons.eot
      create  app/assets/stylesheets/_diamond-icons-rails.scss

Import the generated stylesheet

Next, we'll simply need to import the generated stylesheet. Ideally, we should never need to edit the generated stylesheet (which makes it easier to rebuild as necessary).

application.scss
1
@import "_diamond-icons-rails";

Add a helper method

We can take a look at Font Awesome's source to see how they've implemented their icon helper. We'll make a few customizations!

icon_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
module IconHelper
  def diamond_icon(names, options = {}) # changed helper name
    classes = []
    classes.concat Private.icon_names(names)
    classes.concat Array(options.delete(:class))
    text = options.delete(:text)
    right_icon = options.delete(:right)
    icon = content_tag(:i, nil, options.merge(:class => classes))
    Private.icon_join(icon, text, right_icon)
  end

  module Private
    extend ActionView::Helpers::OutputSafetyHelper

    def self.icon_join(icon, text, reverse_order = false)
      return icon if text.blank?
      elements = [icon, ERB::Util.html_escape(text)]
      elements.reverse! if reverse_order
      safe_join(elements, " ")
    end

    def self.icon_names(names = [])
      array_value(names).map { |n| "diamond-i-#{n}" } # changed class name here
    end

    def self.array_value(value = [])
      value.is_a?(Array) ? value : value.to_s.split(/\s+/)
    end
  end
end

Update the README, so your team can rebuild the font

README.md
1
2
3
4
5
6
7
# Icon font
1. Install Font Custom http://fontcustom.com/
1. Add or update SVGs in `app/assets/icon_svgs/`
1. If any SVGs have spaces in their name, they MUST BE CHANGED TO `-`.
1. From the application root, run `fontcustom compile -c app/assets/icon_svgs/`
1. Remove the `.fontcustom-manifest.json` if it has been created
1. DO NOT edit the `app/assets/stylesheets/_diamond-icons-rails.scss` file.

All done!

Now you can use your new icon instead of, or alongside Font Awesome!

  .icons
    = diamond_icon "diamond-1"
    = diamond_icon "diamond-2"
    = diamond_icon "diamond-3"
    = fa_icon "calendar"

If you enjoyed this post, please let me know on twitter @bolandrm, and/or use the form below to subscribe to my mailing list! Thanks for reading!