2018秋の無料相談会
2018秋の無料相談会
2018.06.26
#150
それいけ!フロントエンド

アイコンファイルをラクラク管理!『SVG sprite』を使いこなそう

はっちゃん

こんちは。はっちゃんです。
みなさんは、iconってどうやって管理してますか?

iconfont化して使ってますか?
png画像単体で使ってますか?
pngのsprite画像で使ってますか?
svg単体で使ってますか?

自分はiconfont一点張りだったんですが、LIGのフロントエンドの中では「元のSVGファイルの管理がしづらいから『SVG sprite』を使ってる」って声がちらほら聞こえるので、今回はそのSVG spriteを本腰入れて使ってみたいと思います。

使い方

SVG spriteの使い方は下記の記事が詳しいので、載っている部分はさらっと流します。
http://design.dena.com/engineering/svg-sprite/

今回、上記記事と異なる部分は以下になります。

  • ディレクトリ構成
  • svg-spriteのglobalインストールなし
  • package.jsonでモジュール管理
  • npm runコマンドを使用

また、nodeのバージョンは8.9.1を。
npmのバージョンは5.6.0を使用します。

ディレクトリ構成

このようなディレクトリ構成でやっていきます。

project
├── src
│ └── assets
│     └── svg-sprite
│         ├── facebook.svg
│         ├── line.svg
│         └── twitter.svg
├── assets
│ └── css
│     └── style.css
├── index.html
├── config.json
└── package.json

package.jsonの中身

{
  "name": "svg-sprite-test",
  "version": "0.1.0",
  "description": "svg sprite test",
  "devDependencies": {},
  "scripts": {
    “svgsprite" :"svg-sprite -C config.json —shape-transform-svgo svgo.json src/assets/svg-sprite/*svg"
  },
  "private": true
}

config.json

{
  "dest": "assets",
  "mode": {
  	"symbol": {
	  "dest" : "svg-sprite",
	  "sprite": "svg-spritesprite.svg"
	}
  }
}

svgo.json

{
  "plugins": [
    { "removeTitle": true },
    { "removeAttrs": { "attrs": ["fill", "id", "data-name"] }}
  ]
}

※idを記載している理由は、最終的にSVG spriteがファイル名をidに付与してくれるから。不要なidを削除して、必要なidだけ残すことができます。

動かしてみる

それではさっそく動かして行きましょう。
先述の記事に使い方の詳細が書かれているので、ここではサクッといっちゃいます。

svg spriteをインストール

npm i svg-sprite —save-dev

package.jsonに書いたsvgspriteコマンドを実行

npm run svgsprite

assets/svg/にsvg-sprite.svgが出力されているかと思います。

backgroundで使用するSVG spriteの書き出し方法

config.jsonとは別にconfig-bg.jsonを用意します。

config-bg.json

{
  "dest": "assets",
  "mode": {
    "css": {
      "dest": "svg-sprite-bg",
      "sprite": "sprite-sprite-bg.svg",
      "bust": false,
      "render": {
        "css": {
          "dest": “../css/svg-sprite-bg.css"
        }
      }
    }
  }
}

src/svg-sprite-bg/の中に、3つのsvgファイルを名前を変えて置いておきます。

  • facebook-bg.svg
  • line-bg.svg
  • twitter-bg.svg

最後にsvgspriteコマンドを下記のように修正します。

"scripts": {
    "svgsprite": "svg-sprite -C config.json —shape-transform-svgo svgo.json src/assets/svg/*svg && svg-sprite -C config-bg.json --shape-transform-svgo svgo.json src/assets/svg-bg/*.svg"
}

実行

npm run svgsprite

assets/svg-sprite-bg配下にsvg-sprite-bg.svg
assets/css配下にsvg-sprite-bg.css
が書き出されているかと思います。

最終的なディレクトリ構成は下記になります。

project
├── src
│ └── assets
│     └── svg-sprite
│         ├── facebook.svg
│         ├── line.svg
│         └── twitter.svg
│     └── svg-sprite-bg
│         ├── facebook-bg.svg
│         ├── line-bg.svg
│         └── twitter-bg.svg
├── assets
│ └── css
│     └── style.css
│     └── svg-sprite-bg.css
├── index.html
├── config.json
├── config-bg.json
└── package.json

HTML、CSSを書いてみる

index.html

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title></title>
	<link href="./assets/css/style.css" rel="stylesheet">
	<link href="./assets/css/svg-sprite-bg.css" rel="stylesheet">
</head>
<body>
	<section>
		<h2>インラインで使用</h2>
		<div class="row">
			<div class="grid">
				<div class="grid-item">
					<div class="svg-facebook">
						<svg class="svg-sprite" role="img">
						<use xlink:href="./assets/svg-sprite/svg-sprite.svg#facebook" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
					</div>
				</div>
				<div class="grid-item">
					<div class="svg-twitter">
						<svg class="svg-sprite" role="img">
						<use xlink:href="./assets/svg-sprite/svg-sprite.svg#twitter" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
					</div>
				</div>
				<div class="grid-item">
					<div class="svg-line">
						<svg class="svg-sprite" role="img">
						<use xlink:href="./assets/svg-sprite/svg-sprite.svg#line" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg>
					</div>
				</div>
			</div>
		</div>
	</section>
	<section>
		<h2>backgroundで使用</h2>
		<div class="row">
			<div class="grid-bg">
				<div class="grid-item-bg">
					<div class="svg-facebook-bg svg-facebook-bg-dims"></div>
				</div>
				<div class="grid-item-bg">
					<div class="svg-twitter-bg svg-twitter-bg-dims"></div>
				</div>
				<div class="grid-item-bg">
					<div class="svg-line-bg svg-line-bg-dims"></div>
				</div>
			</div>
		</div>
	</section>
	<script src="./assets/js/svg4everybody.min.js"></script> 
	<script src="./assets/js/app.js"></script>
</body>
</html>

style.css

section ~ section {
  margin-top: 60px;
}
.row {
  padding: 0 20px;
}
.grid {
  display: flex;
  justify-content: center;
  margin-left: -20px;
  margin-right: -20px;
}
.grid-item {
  padding: 0 20px;
}
.grid-bg {
  display: flex;
  justify-content: center;
  margin-left: -150px;
  margin-right: -150px;
}
.grid-item-bg {
  margin-top: 80px;
  padding: 0 150px;
}

.svg-facebook .svg-sprite {
  fill: #3c599b;
}
.svg-twitter .svg-sprite {
  fill: #2aa3f0;
}
.svg-line .svg-sprite {
  fill: #1bb91f;
}

.svg-facebook-bg {
  transform: scale(4.5);
}
.svg-twitter-bg {
  transform: scale(4.5);
}
.svg-line-bg {
  transform: scale(4.5);
}

svg-sprite-bg.cssは下記のように出力されているのでそのまま使います。

.svg-facebook-bg {
	background: url("../svg-sprite-bg/svg-sprite-bg.svg") 100% 0 no-repeat;
}

.svg-facebook-bg-dims {
	width: 32px;
	height: 32px;
}

.svg-line-bg {
	background: url("../svg-sprite-bg/svg-sprite-bg.svg") 0 100% no-repeat;
}

.svg-line-bg-dims {
	width: 32px;
	height: 32px;
}

.svg-twitter-bg {
	background: url("../svg-sprite-bg/svg-sprite-bg.svg") 0 0 no-repeat;
}

.svg-twitter-bg-dims {
	width: 40px;
	height: 32px;
}

実際に表示してみる

GitHubに公開しました。
https://82mou.github.io/svg-sprite/

まだ自分の中で納得がいっていないのが、backgroundで読み込んでいるSVG spriteのサイズを簡単に管理する方法です。コンパイルで自動で出力されるCSSには、原寸のサイズが記載されています。
実際に案件で使うときは、場所によってはサイズを調整しなければいけないので、background-sizeとwidth、heightを修正する必要があります。

ただ、動的に出力されるCSSの修正はできないので、今回はstyle.cssの方で、transformのscaleで大きさを調整しています。
配置はpaddingで画面見ながら調整したので、この辺をもう少しスマートにできたらいいですね……。

まとめ

いかがでしたか?
IE用にpolifillを入れないと使えませんが、idでひとつひとつのSVGを呼び出せるし、使い勝手はそんなに悪くないです。backgroundでもなんとか動かすことができるので、これからはSVG spriteをスタンダードで使っていきたいと思います。