Generate custom icon fonts from SVG files

Diego Langarica Fuentes
medialesson
Published in
6 min readMar 14, 2024

Icon fonts are a great way to add icons into your applications. Some of their main advantages — on top of the ones shared with SVG-file-based icons, like compact size and scalability — include:

  • Ease of styling. In a web application, this can be done via CSS, just like any other font.
  • All icons are packed into one file, meaning they can be downloaded within a single request, and they share a consistent look and feel.
  • Straightforward implementation across different platforms.

In this post we’ll use FontCustom, a command line tool that uses FontForge in the background, to create our own icon font from a set of SVG files. Let’s get started!

Installation

The project’s repository README provides (outdated) instructions to get the code running. Here is my revised version for MacOS:

brew tap bramstein/webfonttools
brew install woff2 sfnt2woff eot-utils fontforge python-setuptools
sudo gem install fontcustom

Quick setup and results

In order to create our font, let’s first get ourselves some open-license SVG icons from SVG Repo. I’ve downloaded and placed them inside a folder icons/svgs. I’ve also simplified the file names (e.g. to computer.svg), as these will be used for the class names in our results.

All that’s left is to execute the command at the icons folder location:

fontcustom compile svgs

We should get the following output:

By default, the tool generates font files in multiple formats, a CSS file defining the font face and classes for each of the icons matching the original SVG file names, and a preview html file:

/* /icons/fontcustom/fontcustom.css */

/*
Icon Font: fontcustom
*/

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

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

[data-icon]:before { content: attr(data-icon); }

[data-icon]:before,
.icon-chip:before,
.icon-computer:before,
.icon-laptop:before {
display: inline-block;
font-family: "fontcustom";
font-style: normal;
font-weight: normal;
font-variant: normal;
line-height: 1;
text-decoration: inherit;
text-rendering: optimizeLegibility;
text-transform: none;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
font-smoothing: antialiased;
}

.icon-chip:before { content: "\f100"; }
.icon-computer:before { content: "\f101"; }
.icon-laptop:before { content: "\f104"; }
/icons/fontcustom/fontcustom-preview.html

The CSS file contains everything we need to immediately start using the font on a web application. Pretty neat!

We can change the output file format to SCSS by adjusting the tool’s configuration options, and even provide a template to further customise what kind of files should be produced and what they should contain — we’ll take a quick look into it in our next section.

Note on SVG icons

If you are working with your own SVG files, make sure that you are not using any transparency nor clippings, for the conversion to succeed. Also, keep in mind that all colours will be projected to their corresponding grey scale, so you may want to use a grey palette yourself to have better control over the results.

Custom configuration

It’s possible to include multiple options as part of the compile command to adapt the results to a particular project. The full list of options can be consulted via:

fontcustom help

Alternatively, we can run

fontcustom config

to generate a blank YAML config file, which will be used every time fontcustom compile is executed at this location.

Let’s extend our base example to create a SCSS file from a custom template and save the outputs in different destinations.

First, create a template file called _my-icons.scss, under icons/templates. I’ve taken the default SCSS template provided by FontCustom, and made some small modifications:

//
// Icon Font: <%= font_name %>
//

<%= font_face(path: @font_path_alt) %>

.my-icon {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-family: "my-icons";
font-style: normal;
font-weight: normal;
speak: none;
}

<%= glyphs %>

This should replace the whole middle section of our original CSS file above with a single .my-Icon class selector and use a simpler styling.

Now, add a icons/fontcustom.yml file with the following contents:

# =============================================================================
# Font Custom Configuration
# This file should live in the directory where you run `fontcustom compile`.
# For more info, visit <https://github.com/FontCustom/fontcustom>.
# =============================================================================


# -----------------------------------------------------------------------------
# Project Info
# -----------------------------------------------------------------------------

font_name: my-icons
css_selector: .my-icon--{{glyph}}
force: true


# -----------------------------------------------------------------------------
# Input / Output Locations
# -----------------------------------------------------------------------------

input:
vectors: svgs
templates: templates

output:
fonts: fonts
css: styles

templates:
- _my-icons.scss

preprocessor_path: /fonts

This configuration should:

  • Rename our font to my-icons
  • Use my-icon-- as prefix for all of our icon classes
  • Convert the SVG files located in the svgs folder
  • Regenerate all outputs every time, even if there haven’t been any changes in our SVG files
  • Output the font files into a fonts folder
  • Use our _my-icons.scss template located under the templates folder to produce a SCSS file, and save it under a styles folder
  • Use global paths /fonts instead of relative ones when pointing to the generated font files

Let’s try it out by running

fontcustom compile

in the same location as before. Note that specifying the target svgs folder is no longer necessary as it is already defined in our configuration. This returns:

Seems like everything was saved in the correct place, and all our modifications were applied into the SCSS file:

//
// Icon Font: my-icons
//

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

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

.my-icon {
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
display: inline-block;
font-family: "my-icons";
font-style: normal;
font-weight: normal;
speak: none;
}

.my-icon--chip:before { content: "\f100"; }
.my-icon--computer:before { content: "\f101"; }
.my-icon--laptop:before { content: "\f104"; }

Implementation

By importing the outputted CSS / SCSS file into a web project, we can make quick use of it by adding our my-icon and the desired icon classes to a <i> element:

<i class="my-icon my-icon--computer"></i>
<i class="my-icon my-icon--laptop"></i>
<i class="my-icon my-icon--chip"></i>

And style each icon via font-size and color css properties:

That’s pretty much it! I did mention it was straightforward in the list of benefits, didn’t I?

Final words

Despite working like a charm, the FontCustom project has seen virtually not activity in the last years. This might change eventually, with “recent” discussions about the future of the project — involving one of its authors — pointing towards turning the project over. Until then, 🤞.

--

--