3
3

More than 5 years have passed since last update.

必要なアイコンだけSVGで用意して使う

Posted at

動機

Webでよく使うアイコンはせいぜい数種類なのに、Font AwesomeやMaterial Design Iconsなどの「どんどん増えていくWebフォント」を使うのはどうなんだろうと思い、ためしにReactを使ってSVGのアイコンセットのようなものを作ってみました。
結果、アイコンが表示されるまでのラグもなく、タイプ数も若干減らせそうでいい感じです。

デモ

jsfiddleにデモを準備しました。(デモは仕方なくJavaScript1.7です)
アイコンはMaterial Design IconsのSVGを使っています。

sample.png

実用的な使い方

下記のようにモジュールに分け、browserifyとbabelifyを使うのが便利だと思います。

icon.js
import React from 'react';

const Icon = (props) => (
  <svg style={{width: '24px', height: '24px', verticalAlign: 'bottom'}} viewBox="0 0 24 24">
    <path fill={props.color || "#000000"} d={props.d} />
  </svg>
);

export const Image = (props) => (
  <Icon {...props} d="M8.5,13.5L11,16.5L14.5,12L19,18H5M21,19V5C21,3.89 20.1,3 19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19Z" />
);

export const Heart = (props) => (
  <Icon {...props} d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z" />
);

export const Ban = (props) => (
  <svg style={{width: '24px', height: '24px', verticalAlign: 'bottom'}} viewBox="0 0 24 24">
    <path fill={props.color || "#000000"} d="M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z" />
    <path fill={props.color || "#ff0000"} d="M12,0A12,12 0 0,1 24,12A12,12 0 0,1 12,24A12,12 0 0,1 0,12A12,12 0 0,1 12,0M12,2A10,10 0 0,0 2,12C2,14.4 2.85,16.6 4.26,18.33L18.33,4.26C16.6,2.85 14.4,2 12,2M12,22A10,10 0 0,0 22,12C22,9.6 21.15,7.4 19.74,5.67L5.67,19.74C7.4,21.15 9.6,22 12,22Z" />
  </svg>
);

Iconを使うところは、下記のようなイメージです。(Bootstrap4を使っています)

script.js
import React from 'react';
import ReactDOM from 'react-dom';

import * as Icon from './icon';

const MdiButtons = React.createClass({
  render() {
    return (
      <div>
        <button type="button" className="btn btn-link"><Icon.Image /></button>
        <button type="button" className="btn btn-link"><Icon.Heart color="pink" /></button>
        <button type="button" className="btn btn-danger-outline"><Icon.Ban /> Ban</button>
      </div>
    );
  }
});

ReactDOM.render(<MdiButtons />, document.getElementById('container'));
参考html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css">
  </head>
  <body>
    <div id="container"></div>
    <script src="bundle.js"></script>
  </body>
</html>

下記は、browserifyでbundle.jsを準備する例です。
$ browserify script.js -o bundle.js -t [ babelify --presets [ es2015 react ] ]

(gulp等を使う方がもっと実用的です。)

おわりに

もともと用意されている「使い方」とは外れてしまうため、管理面等でリファレンスを作るといった手間が増えてしまうかもしれません。
ただ、それを上回るメリット、例えば本記事のような「アイコンのスタック」がしやすいなどのカスタマイズ性が魅力で、もう少しコードを洗練すれば、もっと便利になるんじゃないかと考えています。
また、変にCSSを汚染しない点も気に入っています。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3