All well-known web icon sets are shipped in the format of fonts. For example, it is Fontawesome Webfont which ships in woff2 / eot / ttf formats.

Here I will show how to craft such icon Webfont from your custom svg icons. Delivering icons with Webfont allows loading them in the most efficient way and ensure text remains visible during webfont load.

This method works for any npm-based project (e.g. SPAs like React, Vue.js etc). Idea is next:

  1. Collect some SVG files into one folder in the project, for example, exported from Figma or vector graphics editor
  2. Create a npm script that will generate ttf / woff / eot fonts + CSS file which will import and connect them
  3. Then you will need just connect/import CSS file into your app
  4. Every time when you change or add an icon, you need only rerun npm script

Some times ago before 2017 there was a great package called webfonts-generator which generated webfont using another library [email protected]. But maintainer stopped work on webfonts-generator, when svgicons2svgfont got several great updates and fixes (up to 9.x.x) – most important fix of the messed look of icons after webfont generation. So we've found a new fork @vusion/webfonts-generator using this method and we will explain how to integrate it into your app.

First, install it into your app:

npm i @vusion/webfonts-generator

Now create script generate_font.js which will run the generator:

const webfontsGenerator = require('@vusion/webfonts-generator');
const fs = require('fs');

fs.readdir('res/font', function(err, items) {
  if (err) {
    console.log('cant read res directory');
  }
  const files = items.filter((i) => i.toLowerCase().endsWith('.svg')).map(
    (i) => 'res/font/'+i);

  webfontsGenerator({
    files: files,
    dest: 'css/icons',
    fontName: 'ptroiconfont',
    
    // https://github.com/nfroidure/svgicons2svgfont options
    normalize: true,
    
    cssTemplate: 'res/font/font-css.hbs',
    templateOptions: {
      classPrefix: 'my-icon-',
      baseSelector: '.my-icon'
    },
    types: ['svg', 'ttf', 'woff', 'eot']
  }, function (error) {
    if (error) {
      console.log('Fail!', error);
    } else {
      console.log('Done!');
    }
  })
})

Now place icons to res/font/ folder.

Also, create a file res/font/font-css.hbs (This is a template for CSS file which will hold needed styles):

@font-face {
	font-family: "{{fontName}}";
	src: {{{src}}};
	font-weight: normal;
    font-style: normal;
}

{{baseSelector}} {
}

{{baseSelector}}:before {
	font-family: {{fontName}} !important;
	font-style: normal !important;
	font-weight: normal !important;
	font-variant: normal !important;
	text-transform: none !important;
	speak: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

{{#each codepoints}}
.{{../classPrefix}}{{@key}}:before {
	content: "\\{{this}}";
}
{{/each}}

Add script to package.json scripts section:

"scripts": {
    "buildfont": "node generate_font.js"
},

And run it now and every time when you will change icons:

npm run buildfont

Include generated css file into your app and make sure it loads font files correctly (using Devtools ➡ Network).

To use icons in HTML or your SPA templates (Vue.js, React), add this:

<i class="my-icon my-icon-apply"></i>

Troubleshooting

You don't see icon details in fornt

First of all, you might know that underlying svgicons2svgfont library does not support stroke at all: Empty glyph when icon is made of strokes (Though many browsers also can't render it).

In this case, just import SVG icon in Figma (free) and click Outline stroke:

Image for a hint

Then export back from Figma

Paths are filled when should not

Another typical issue.

The reason – not supported reverse directions for paths. You will understand what is it, but the first example:

Paths are filled in vector font

The cause of this issue: the algorithm to use to determine the inside part of a shape. The algorythom defined by fill-rule attribute of path tag inside of svg. The default value which is compatible to most of rendering and converter programs (including webfonts generators) is nonzero. However there is another value evenodd which rarely supported. You might confirm the issue by opening your SVG file in text editor:

fill-rule="evenodd"

⛔ Don't think you can just delete the attribute from SVG source and it should fix it. It will not work. The attribute produced by drawing tool (Inkspape, AI, figma, etc) used only help SVG renders and converters to draw pathes (which defined in d attribute of path tag), but if you just remove attribute, path direction in d will be same. Anyway this attribute is ignored by svgicons2svgfont at all. See: It seems that fill-rule="evenodd" does not works correctly
🤷‍♂️ Why it is not working? Tooling which we are using is an open source and created by a great guys who spend a time on creating tools for their need and share them with us for free! Most time they don't receive a revenue but spend a lot of time on creting tools, so the tool itself should be enough to satisfy minimal working flow. So you need just change direction of path by yourself, same like with strokes.

So, let's fix it!

First, install Fill Rule Editor plugin into your free Figma.

Drag and drop or paste SVG icon which looks odd in font and open plugin:

Fill Rule Editor

Now select pathes (click on gray area of any), we see that in Even-Odd rule it looks right:

Even-Odd fix 1

Now click on orange area to switch rule, we see it screwed up:

Even-Odd fix 2

This mode is default so supported by most of tools. And now to fix it, click on internal or external outline:

Even-Odd fix 3

🤔Reversing path direction tooling exists in Inkskape, AI and other vector graphic software, but this Figma plugin is much simpler and it is free, so we suggest to use it

Generate a webfont