Iconfont: generation via Gulp.js

Update of 25/06/2015: multiple changes due to gulp-iconfont updates.

Hello everyone !
This is my first article on the UX-Republic blog and I will explain how I generate an iconfont from files SVG quickly and as unobtrusively as possible using Gulp.js.
iconfont Gulp.js

Why?

Before using Gulp.js to generate an iconfont, I went through the service IcoMoon App.
It works very well but many steps are necessary before you see an icon appear on your browser:

  • go to the page,
  • import the SVGs (browse its files on your computer),
  • select its icons,
  • click on “Generate Font”,
  • click on “Download”,
  • unzip the archive,
  • move font files,
  • copy/paste the CSS.

And if something has been forgotten or the SVG file is not correct… you have to start all over again.
The purpose of this exercise carried out with Gulp.js is to make automatic the addition of an icon to its iconfont. That the only action to do is to move its SVG file into a folder and execute a single command in the terminal to start the generation of our iconfont (font and CSS).

Prerequisites

First of all you will have to install some tools on your computer to be able to generate your iconfont.

Node.js

NodeJS logoNode.js is a network-oriented software platform. It allows the use of JavaScript elsewhere than in a web browser.
You need to download the installer and run it like installing any program. You can already do it by following the following link: https://nodejs.org/download/.

Gulp.js

Gulp Js LogoGulp.js is a program developed as its name suggests in JavaScript (extension .js). It is he who will allow us to carry out our tasks.
To install it as easily as possible, we will do it from the command line using a terminal.

Project configuration

Let's start by creating a folder in which we will put all the files and install the modules we will need to generate our iconfont.
Here is the structure I propose:

iconfont_project
    \css
    \fonts
        \custom
    \icons
    \scss
        \templates
            _icons.scss
        _icons.scss
        fonts.scss
        main.scss
    gulpfile.js
    index.html

Open a terminal and navigate to the project folder.
You have to create a file package.json which will aim to gather all the information of the project (name, version, modules used, etc.).
To do this, type the following command:

npm init

Install Gulp.js

To install Gulp.js, type the command:

npm install --save-dev gulp

Install Gulp.js modules

We need several modules for our project:

To install them, type this command:

npm install --save-dev gulp-sass gulp-iconfont gulp-consolidate lodash

You should see a new folder named “node_modules” appear, this is where Gulp.js and its modules are installed.

Write the Gulpfile

The file gulpfile.js is the file where we will write our tasks that will be used to generate font files and CSS.
We start by calling our previously downloaded libraries:

var gulp = require('gulp')
  , sass = require('gulp-sass')
  , iconfont = require('gulp-iconfont')
  , consolidate = require('gulp-consolidate');

We write our iconfont function (you will find the commented code on GitHub at the end of the article):

gulp.task('iconfont', function () {
  gulp.src('icons/**/*.svg')
    .pipe(iconfont({
      fontName: 'custom'
    , centerHorizontally: true
    , normalize: true
    , appendUnicode: true
    }))
    .on('glyphs', function (glyphs) {
      gulp.src('scss/templates/_icons.scss')
        .pipe(consolidate('lodash', {
          glyphs: glyphs
        , fontName: 'custom'
        , fontPath: '../fonts/custom/'
        , className: 'icon'
        }))
        .pipe(gulp.dest('scss'));
    })
    .pipe(gulp.dest('fonts/custom'));
});

A second function called “sass” to compile our CSS:

gulp.task('sass', function () {
  gulp.src('scss/**/*.scss')
    .pipe(sass({
      indentWidth: 4
    , outputStyle: 'expanded'
    }))
    .pipe(gulp.dest('css'));
});

Gulp.js requires a default function that should be named default:

gulp.task('default', ['sass'], function () {
  gulp.watch('scss/**/*.scss', ['sass']);
});

In this function we execute the “sass” function then we tell Gulp.js to look if one of our Sass files is modified. If so, it will run the “sass” function again.

Creation of the template

The template is a Sass file in which we will put the variables of the information that we wrote in our gulpfile.js file, namely the name of our font, the path of our font files, etc.
We will also retrieve the table where the “code points” are stored. This is the code that will be inserted into the CSS content.
Please note: the script will take the name of the SVG you gave it.
Here is an example of what will be generated in CSS if I name my SVG file “myicon.svg”:

.icon-myicon:before {
    content: "\E001";
}

We will write our template in the scss/templates folder.
Let's start by writing the @font-face that will call our iconfont:

@font-face {
    font-family: '<%= fontName %>';
    font-weight: normal;
    font-style: normal;
    src: url('<%= fontPath %><%= fontName %>.eot');
    src: url('<%= fontPath %><%= fontName %>.woff2') format('woff2'),
         url('<%= fontPath %><%= fontName %>.woff') format('woff'),
         url('<%= fontPath %><%= fontName %>.ttf') format('truetype'),
         url('<%= fontPath %><%= fontName %>.eot?#iefix') format('embedded-opentype');
}

Everything contained in “<%=” and “%>” is actually JavaScript code. "fontName" and "fontPath" are variables that take the parameters that we wrote in the "consolidate" method of our "iconfont" task located in our gulpfile.js.
We then write the main class in which we will call the font via font-family as well as the styles specific to the fonts which we initialize to the default value to override the styles which could be applied on the parent tags where our icon would be:

.<%= className %>[class^="<%= className %>-"],
.<%= className %>[class*=" <%= className %>-"] {
    display: inline-block;
    font-family: '<%= fontName %>';
    -moz-osx-font-smoothing: grayscale;
    -webkit-font-smoothing: antialiased;
    font-style: normal;
    font-variant: normal;
    font-weight: normal;
    line-height: 1;
    text-transform: none;
}

The last two properties are used to trigger the effect Cleartype in order to have a better rendering by activating antialiasing.
We will then create a loop to build a map that we will name "icons".
A map is a data type in Sass that allows you to structure data by key / value pair.

$icons: (
    <%= glyphs.map(function(glyph) {
        return glyph.name + ': '\' + '\\' + glyph.unicode[0].charCodeAt(0).toString(16).toUpperCase() + ''\'
    }).join(',\n ') %>
);

"glyphs" (JavaScript variable, see gulpfile.js file) is an array containing objects and for each of them we will execute a function that will return the name of the glyph (glyph.name) which is the name of the file SVG you gave it. These names will be the keys to the Sass map.
For the values ​​of the map we return the code points (glyph.codepoint) that we convert into hexadecimal and that we transform into uppercase.
Once the map is generated, it gives this:

$icons: (
    antenna: '\E001',
    heart: '\E002'
);

And finally we create a loop (in Sass language this time) which will be used to read each element of our map and generate the CSS:

@each $name, $icon in $icons {
    .<%= className %>-#{$name}:before {
        content: $icon;
    }
}

In the each loop, the first variable “name” contains the keys of the map and the second “icon” contains the values.
Then we write the CSS. In <%= className %> we will have the value “icon” (assigned in the gulpfile.js file).
#{$name} is our key with the class name.
$icon is our value with the dot code.
Why #{$name} and not just $name?
We write a variable inside a character string and we use here what we call thethe interpolation.
When we run our “iconfont” task, it will take the sass/templates/_icons.scss file, run the JavaScript code, and generate the sass/_icons.scss file. It is the "sass" task that will generate the CSS.

Run Gulp.js to generate the iconont

To generate the font files and the SCSS, we need to run our “iconfont” task like this:

gulp iconfont

To compile the Sass code to CSS, we'll run our "default" function:

gulp default

Gulp.js has simplified things, we can omit the word "default", it will still run our task by default:

gulp

Use our new icon

If we take the example above, to display our icon we must write a tag with the icon class which is the main class and the icon-myicon class which contains the content.
Example:

<i class="icon icon-myicon"></i>

Conclusion

It takes a little time to set everything up but during a project, adding an icon to your web font is done in seconds.
All the files are on the GitHub of UX-Republic, you can download them at this address: https://github.com/ux-republic/gulp-icon-font.
Feel free to ask your questions in the comments.