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:
- Uploading the json file in icomoon. We keep the generated selection.json file in our VCS Mercurial.
- Add the new icons to the selection.
- Generate the font.
- Replace the old font icon files with the new ones.
- Update your scss file.
- Compile scss file to css.
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.