Posted 5 months ago. Visible to the public. Repeats.

Webpack: Automatically generating an icon font from .svg files

Over the years we have tried several solution to have vector icons in our applications. There are many ways to achieve this, from SVGs inlined into the HTML, SVGs inlined in CSS, JavaScript-based solutions, to icon fonts.

Out of all these options, the tried and true icon font seems to have the most advantages, since

  • icon fonts are supported everywhere
  • they perform well and require no JavaScript at all
  • their icons align nicely with text
  • their icons automatically inherit color and size of the surrounding text

The big issue used to be building the font itself was very cumbersome. Luckily, there are webpack plugins out there, such as iconfont-plugin-webpack that automate the font building.

If you're still using the Rails asset pipeline, try the half-automatic approach.

Webpacker Rails: How to integrate the plugin

Copy
yarn add iconfont-plugin-webpack yarn add resolve-url-loader

Add these lines to your environment.js:

Copy
const IconfontPlugin = require('iconfont-plugin-webpack') environment.plugins.append( // https://www.npmjs.com/package/iconfont-plugin-webpack 'Iconfont', new IconfontPlugin({ src: './app/webpack/images/icons', family: 'icons', dest: { font: './tmp/webpack/generated/fonts/icon_font/[family].[type]', css: './tmp/webpack/generated/_icon_font_[family].scss' }, watch: { pattern: 'app/webpack/images/icons/*', cwd: undefined }, }) ) // unfortunately, we need to adjust the sass-loader and add an additional `resolve-url-loader`, otherwise // the relative url(./fonts/...) entries generated by the IconfontPlugin will not work const sassLoaderConfig = environment.loaders.get('sass') const sassLoaderIndex = sassLoaderConfig.use.findIndex(config => { return config.loader === 'sass-loader' }) sassLoaderConfig.use[sassLoaderIndex].options.includePaths = ['tmp/webpack'] sassLoaderConfig.use.splice(sassLoaderIndex, 0, { loader: 'resolve-url-loader', })

Put all your icons into app/webpack/images/icons/.

Import the icon-font by adding a file icon_font.sass:

Copy
$icon-prefix: '-' @import "generated/icon_font_icons" $size: 1em * $line-height-base // only works with bootstrap .icon // adjust some styles display: inline-block width: 1em height: 1em font-size: $size -moz-osx-font-smoothing: grayscale -webkit-font-smoothing: antialiased text-rendering: auto font-style: normal font-weight: normal line-height: 1 // We can not use "vertical-align: middle" to vertically center the font, or icon containers // cause their surrounding containers to grow. The follow produces the desired result. vertical-align: text-bottom margin-bottom: -.1em

Now, in your HTML, you can add an icon with

Copy
<i class="icon -name-of-the-icon"></i>

Icon names are simply the file names of the SVGs.

If you want to use icons in Sass, you use the following:

Copy
// probably want to do this in a generic _mixins.sass: $create-font-face: false $create-icon-classes: false @import generated/icon_font_icons .my-element +iconfont(icon-name)

Known issues

  • When you add a new icons, our usual live reload might not pick it up, and you have to reload your page manually.
  • I've seen one case where an SVG file was not converted properly into the fonts. The issue was a transform attribute on a <use> tag that was seemingly ignored. I was able to fix the affected SVG with my text editor.

Once an application no longer requires constant development, it needs periodic maintenance for stable and secure operation. makandra offers monthly maintenance contracts that let you focus on your business while we make sure the lights stay on.

Owner of this card:

Avatar
Tobias Kraze
Last edit:
3 months ago
by Tobias Kraze
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Tobias Kraze to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more