Gulpでアイコンフォントを自動生成する方法

アイコンフォントを作成するにはIcoMoonが有名ですが、外部サービスなのでgitでの管理が面倒だったりします。
gulpではほぼ同じ処理が実現できます。つまりローカルで完結するのでファイル管理が楽になります。

gulpでアイコンフォントを自動生成する方法

ディレクトリ構成

.
├── assets
│   ├── css
│   └── fonts
├── gulpfile.js
└── src
    ├── iconfont
    │   ├── svg
    │   └── templates
    │       ├── myfont.css
    │       ├── myfont.html
    │       └── myfont.scss
    └── sass
        ├── foundation
        │   └── base
        └── style.scss

必要ライブラリをインストール

npm i gulp-iconfont gulp-consolidate gulp-rename lodash -D

gulpfile.jsにタスクを書く

var gulp = require("gulp");

var rename = require('gulp-rename');
var iconfont = require('gulp-iconfont');
var consolidate = require('gulp-consolidate');
var runTimestamp = Math.round(Date.now()/1000);
var fontName = 'myfont'; // アイコンフォント名

gulp.task('sass', function(){
  gulp.src('src/sass/*scss')//scssファイルのディレクトリを指定
    .pipe(plumber())//エラーが起きても監視を続行
    .pipe(sass({outputStyle: 'compressed'}))//圧縮:compressed 未圧縮:expanded
    .pipe(gulp.dest('assets/css/'));//指定のディレクトリにcssを出力
});

//アイコンフォント作成タスク
gulp.task('Iconfont', function(){
  gulp.src(['src/iconfont/svg/*.svg'])
  .pipe(iconfont({
    fontName: fontName, // required
    timestamp: runTimestamp,
    formats: ['ttf','eot','woff','svg']
  }))
  .on('glyphs', function(glyphs, options) {
    engine = 'lodash',
    consolidateOptions = {
      glyphs: glyphs,
      fontName: fontName,
      fontPath: '/assets/fonts/', // cssからのフォントパスを指定 ※cssからの相対パスでフォントを指定してもOK
      className: 'myfont', // cssのフォントのクラス名を指定
    }
    // アイコンフォント用のscssを作成(実装用)
    gulp.src('src/iconfont/templates/myfont.scss')
    .pipe(consolidate(engine, consolidateOptions))
    .pipe(rename({ basename: '_' + fontName }))
    .pipe(gulp.dest('src/sass/foundation/base/')); // scssの吐き出し先を指定
    // アイコンフォント用のcssを作成(プレビュー用)
    gulp.src('src/iconfont/templates/myfont.css')
    .pipe(consolidate(engine, consolidateOptions))
    .pipe(rename({ basename:fontName }))
    .pipe(gulp.dest('src/iconfont/')); // scssの吐き出し先を指定
    // アイコンフォント一覧のサンプルHTMLを作成(プレビュー用)
    gulp.src('src/iconfont/templates/myfont.html')
    .pipe(consolidate(engine, consolidateOptions))
    .pipe(rename({ basename:'sample' }))
    .pipe(gulp.dest('src/iconfont/')); // サンプルhtmlの吐き出し先を指定
  })
  .pipe(gulp.dest('assets/fonts/'));
});

gulp.task("watch", function() {
  gulp.watch('src/iconfont/svg/*.svg', ['Iconfont']);
});

gulp.task('default', ['watch']);

テンプレートを準備

アイコンプレビュー用のcss

@font-face {
    font-family: "<%= fontName %>";
    src: url('../../assets/fonts/<%= fontName %>.eot');
    src: url('../../assets/fonts/<%= fontName %>.eot?#iefix') format('eot'),
        url('../../assets/fonts/<%= fontName %>.woff') format('woff'),
        url('../../assets/fonts/<%= fontName %>.ttf') format('truetype'),
        url('../../assets/fonts/<%= fontName %>.svg#<%= fontName %>') format('svg');
    font-weight: normal;
    font-style: normal;
}
.<%= className %> {
    display: inline-block;
    font-family: "<%= fontName %>";
    font-style: normal;
    font-weight: normal;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
.<%= className %>-lg {
    font-size: 1.3333333333333333em;
    line-height: 0.75em;
    vertical-align: -15%;
}
.<%= className %>-2x { font-size: 2em; }
.<%= className %>-3x { font-size: 3em; }
.<%= className %>-4x { font-size: 4em; }
.<%= className %>-5x { font-size: 5em; }
.<%= className %>-fw {
    width: 1.2857142857142858em;
    text-align: center;
}
<% _.each(glyphs, function(glyph) { %>.<%= className %>-<%= glyph.name.slice(4) %>:before { content: "\<%= glyph.unicode[0].charCodeAt(0).toString(16).toUpperCase() %>" }
<% }); %>

アイコンプレビュー用のhtml

<html>
    <head>
        <title><%= fontName %></title>
        <link href="<%= fontName %>.css" rel="stylesheet">
        <style>
            body { font-family: Gill Sans; text-align: center; background: #f7f7f7 }
            body > h1 { color: #666; margin: 1em 0 }
            .glyph { padding: 0 }
            .glyph > li { display: inline-block; margin: .3em .2em; width: 6em; height: 6.5em; background: #fff; border-radius: .5em; position: relative }
            .glyph > li span:first-child { display: block; margin-top: .1em; font-size: 4em; }
            .glyph-name { font-size: .8em; color: #999; display: block }
            .glyph-codepoint { color: #999; font-family: monospace }
        </style>
    </head>
    <body>
        <h1><%= fontName %></h1>
        <ul class="glyph"><% _.each(glyphs, function(glyph) { %>
            <li>
                <span class="<%= className %> <%= className %>-<%= glyph.name.slice(4) %>"></span>
                <span class="glyph-name"><%= glyph.name.slice(4) %></span>
                <span class="glyph-codepoint">\<%= glyph.unicode[0].charCodeAt(0).toString(16).toUpperCase() %></span>
            </li><% }); %>
        </ul>
    </body>
</html>

実際に組み込むscss

@font-face {
    font-family: "<%= fontName %>";
    src: url('<%= fontPath %><%= fontName %>.eot');
    src: url('<%= fontPath %><%= fontName %>.eot?#iefix') format('eot'),
        url('<%= fontPath %><%= fontName %>.woff') format('woff'),
        url('<%= fontPath %><%= fontName %>.ttf') format('truetype'),
        url('<%= fontPath %><%= fontName %>.svg#<%= fontName %>') format('svg');
    font-weight: normal;
    font-style: normal;
}
.<%= className %> {
    display: inline-block;
    font-family: "<%= fontName %>";
    font-style: normal;
    font-weight: normal;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}
.<%= className %>-lg {
    font-size: 1.3333333333333333em;
    line-height: 0.75em;
    vertical-align: -15%;
}
.<%= className %>-2x { font-size: 2em; }
.<%= className %>-3x { font-size: 3em; }
.<%= className %>-4x { font-size: 4em; }
.<%= className %>-5x { font-size: 5em; }
.<%= className %>-fw {
    width: 1.2857142857142858em;
    text-align: center;
}
<% _.each(glyphs, function(glyph) { %>.<%= className %>-<%= glyph.name.slice(4) %>:before { content: "\<%= glyph.unicode[0].charCodeAt(0).toString(16).toUpperCase() %>" }
<% }); %>

実行

ここまで準備ができたらあとは実行するだけです。

gulp

これでsrc/iconfont/svgフォルダが監視状態になり、
svgファイルを入れるだけでアイコンフォントが自動生成されます!

作成したフォントのプレビュー

src/iconfont直下にsample.htmlが生成されているのでそれをブラウザで開くだけで確認できます。

各アイコンの下のフォント名と文字コードは実際にアイコンフォントを表示する際に使用します。
表示方法については後述します。

svgファイルを作成するにあたっての注意点

  • 高さ500px以上
  • 全てシェイプであること
  • ファイル名を001-xxxx.svgのように3桁の連番+ハイフンを接頭辞にする

svgファイル名を上記のようにする理由はアイコンがファイル名順に生成されるため。
文字コードもファイル名順に割り当てられるためファイルの順番が変わると違うアイコンが表示されたりする。

作成したアイコンフォントを実際に表示する方法

src/sass/foundation/baseにmyfont.scssが作成されているはずなのでそれをstyle.scssにインポートして使用します。

@charset "UTF-8";

@import "foundation/base/myfont";

Sassのコンパイルについてはコチラの記事をご確認ください

htmlタグで使用

<i class="myfont myfont-xxxx"></i>

xxxxはフォント名

疑似要素で使用

<i class="icon-xxxx"></i>
.icon-xxxx {
  &:before {
    font-family: "myfont"
    content: "\EA01"
  }
}

class名は何でもOK
font-familyは今回はmyfont ※gulpfile.jsで指定している
contentに文字コード

以上でgulpでアイコンフォントを自動生成環境の完成です。

参考サイト

https://www.tam-tam.co.jp/tipsnote/javascript/post11005.html

http://atsu666.com/entry-78.html