How to generate a webfont [automated setup]
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:
- Collect some SVG files into one folder in the project, for example, exported from Figma or vector graphics editor
- Create a npm script that will generate ttf / woff / eot fonts + CSS file which will import and connect them
- Then you will need just connect/import CSS file into your app
- 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:
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:
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:
⛔ 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 ind
attribute ofpath
tag), but if you just remove attribute, path direction ind
will be same. Anyway this attribute is ignored bysvgicons2svgfont
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:
Now select pathes (click on gray area of any), we see that in Even-Odd rule it looks right:
Now click on orange area to switch rule, we see it screwed up:
This mode is default so supported by most of tools. And now to fix it, click on internal or external outline:
🤔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