Font icons with Fontcustom and Sass

November 21, 2015

In 2013 and 2014 I used Icomoon to create font icons. It is a nice library and tool. You can choose icons from their library and they have the feature to upload your own svgs to create the font icon set. It is a great tool if you only need to generate the font icon once. But not when you have to add new ones to the set.

At Dreamsolution the company where I'm employed, the development and design goes in iterations. When the first design is approved I can create with Icomoon the font icon set at once. But as the development and design iterations continues, new icons are created. When using Icomoon I have to go through several steps to update my font icon set:

That is quite a few steps I have to go through, to update my font icon set. So how can this workflow be more efficient? 3 Months ago I read somewhere about Fontcustom, not sure if it was an article in cssweekly or the Webdesigner Magazine (Dutch version), but it caught my attention. Fontcustom is a command line tool to generate the font icon, based on a selection of svg files. It generates the css + preview html on the fly. And with Fontcustom I am able to speed up my workflow when new icons are to be implemented.

How to set up Fontcustom to speed up my workflow

In my daily work I use Sass, and Fontcustom has the feature to generate .scss file. This is very neat, but the generated .scss file is similar to the generated css file: it defines for each icon an icon class, and when you have, let's say 30 icons, it's get cluttered.

    
    .icon-arrow-down::before {
        content: "";
    }
    .icon-arrow-left::before {
        content: "";
    }
    
    

I wanted to use the SASS maps feature to get a nice list of all the icons and use an @each loop to generate the classes. How do I get Fontcustom generate the output I want? First you need to have your project structure ready and Fontcustom installed. My project structure looks like this:

    FOO-project/
    static/
      foo-icons/
         fontcustom.yml
         _icons.scss /* Is the template which will create the _icons.scss partial file \*/
         foo-icons-preview.html /* This file is generated by fontcustom \*/
         svg/
            checkmark.svg
            arrow-right.svg
            arrow-left.svg
            trash.svg
       fonts/
       scss/
          base.scss
          _fonts.scss
    
    

Fontcustom.yml

The two main files which will do the work are fontcustom.yml config file and the _icons.scss fontcustom template file. There are a lot of configuration options, but in this example I highlight the ones which are important for this example. Personally I run the fontcustom command from the root of the project directory, that's why I use the complete path in the config file. Now let's take a look at my fontcustom.yml file:

    
    # =============================================
    # Font Custom Configuration, for more info,
    # visit https://github.com/FontCustom/fontcustom.
    # ===============================================
    font_name: foo-icons

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

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

    input:
      vectors: FOO-project/static/foo-icons/svg
      templates: FOO-project/static/foo-icons

    output:
      fonts: FOO-project/static/fonts
      preview: FOO-project/static/foo-icons
      _icons.scss: FOO-project/static/scss

    templates: [_icons.scss, preview]
    
    

SCSS fontcustom template

The configuration file is ready, now I have to create the _icons.scss template which will output the desired scss partial :

    
    // This will generate the @font-face
    <%= font_face(path: "fonts/" + font_name) %>

    // This generates the SASS map:
    $font-icons: (<% @glyphs.each do |name, value| %>
    "<%= name.to_s %>": "\<%= value[:codepoint].to_s(16) %>",<% end %>
    );

    @each $icon, $unicode in $font-icons {
        .icon-#{$icon}::before {
            content: $unicode;
        }
    }
    
    

Generate the font icon and _icons.scss partial

Everything is in place and I can run the fontcustom command from the root of the directory to generate the font icon set and scss partial.

    
    $ fontcustom compile -c static/foo-icons/fontcustom.yml
    
    

The project structure is updated with the font icon and scss partial:

    
    FOO-project/
    static/
      foo-icons/
         fontcustom.yml
         _icons.scss /* Is the template which will create the _icons.scss partial file */
         foo-icons-preview.html /* This file is generated by fontcustom */
         svg/
            checkmark.svg
            arrow-right.svg
            arrow-left.svg
            trash.svg
       fonts/
          foo-icons.eot
          foo-icons.svg
          foo-icons.ttf
          foo-icons.woff
       scss/
          base.scss
          _fonts.scss
          _icons.scss /* generated icons partial */
    
    

Let's take a look at the generated _.icons.scss file. It contains the structure and info I wanted: @font-face declaration, the SASS map and the @each loop:

    
    @font-face {
        font-family: "foo-icons";
            src: url("fonts/foo-icons.eot");
            src: url("fonts/foo-icons.eot?#iefix") format("embedded-opentype"),
                url("fonts/foo-icons.woff") format("woff"),
                url("fonts/foo-icons.ttf") format("truetype"),
                url("fonts/foo-icons.svg#foo-icons") format("svg");
        font-weight: normal;
        font-style: normal;
    }

    @media screen and (-webkit-min-device-pixel-ratio:0) {
          @font-face {
              font-family: "foo-icons";
              src: url("fonts/foo-icons.svg#foo-icons") format("svg");
          }
      }

      $font-icons: (
          "arrow-down": "\f100",
          "arrow-left": "\f101",
          "arrow-right": "\f102",
          "arrow-up": "\f103",
          "calendar": "\f104",
          "checkmark": "\f10f",
          "close": "\f111",
          "edit": "\f110",
          "graph": "\f105",
          "help": "\f112",
          "lock-closed": "\f106",
          "lock-open": "\f107",
          "plus": "\f108",
          "projects": "\f113",
          "search": "\f109",
          "tag": "\f10a",
          "tags": "\f10b",
          "trash": "\f10c",
          "user": "\f10d",
          "users": "\f10e",
      );

    @each $icon, $unicode in $font-icons {
        .icon-#{$icon}:before {
            content: $unicode;
        }
    }
    
    

Final steps

The final step is to make sure that every class that starts with or contains "icon-" will use the foo-icons font and that _icons.scss is included. I added the following code to my _fonts.scss:

    
    @import "_icons";

    [class*=" icon-"]::before {
        display: inline-block;
        font-family: "foo-icons";
        speak: none;
        font-style: normal;
        font-weight: normal;
        font-variant: normal;
        text-transform: none;
        line-height: 1px;
        vertical-align: top;
        padding-top: 7px;
    }
    
    

My configuration is in place and when I have new icons to add, I just have to add the new icons to my svg directory and run the fontcustom command and scss command. The 6 slow steps are reduced to 3 faster steps.

I hope this article is meaningful to you and if you have any questions or remarks you can find me on twitter @mirelvt.