SVGは思ってたより怖くなかった。インラインSVGのススメ

最近SVGに初めて触れる機会があり、それまで抱いていたイメージとは大きく違ったものだという感想を持った。この記事では、これまでSVGに触れたことのない人向けに「SVGのそんなに怖くないところ」を紹介する。

# SVGになんとなく抱いていた印象

* ベクター形式のなんかよく分かんない画像まわりの最新技術
* 仕事で実用するには新しすぎる
* 使いこなすには何か高度で新しい技術を勉強しないと無理
* 中を覗くと数字がたくさんあって難しそう。算数嫌い

```xml
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><path d="M112.8 234.8c-2.4-1.5-7.6-3.8-14.6-3.8-11.5 0-15.9 7.1-15.9 13 0 8.2 5 12.3 16.1 17 13.4 5.7 20.2 12.5 20.2 24.4 0 13.2-9.6 23.3-27.4 23.3-7.5 0-15.7-2.3-19.8-5.2l2.5-7.5c4.5 2.9 11.1 5.1 17.8 5.1 11.1 0 17.6-6 17.6-14.9 0-8.2-4.5-13.2-15.2-17.5-12.5-4.7-21-12-21-23.4 0-12.6 10.2-21.9 25.3-21.9 7.8 0 13.8 2 17 3.9l-2.6 7.5zM188.8 224.6l-28.5 82.8h-9.6l-26.2-82.7h9.8l12.7 41.5c3.5 11.2 6.5 21.6 8.7 31.3h.3c2.2-9.7 5.5-20.4 9.2-31.3l13.8-41.6h9.8zM256.8 304c-4.5 1.7-13.2 4.2-23.6 4.2-32.5 0-40.2-24.2-40.2-41.7 0-25.2 16.4-42.7 42.4-42.7 7.9 0 15 1.5 19.1 3.5l-2.4 7.5c-4-1.8-9.2-3.4-17-3.4-19.6 0-32.7 12.6-32.7 34.6 0 22.4 12.5 34.9 31.4 34.9 7 0 11.6-1.1 14-2.4V272h-16.7v-7.3h25.7V304zM357.2 304c-4.5 1.7-13.2 4.2-23.6 4.2-32.5 0-40.2-24.2-40.2-41.7 0-25.2 16.4-42.7 42.4-42.7 7.9 0 15 1.5 19.1 3.5l-2.4 7.5c-4-1.8-9.2-3.4-17-3.4-19.6 0-32.7 12.6-32.7 34.6 0 22.4 12.5 34.9 31.4 ... </svg>
```

# 使ってみて分かったこと

* 数字の羅列はIllustratorが作るので、ほとんどどうでもいい
* 要素や属性名は見なれないが、HTMLの中に混ぜても全然OK。むしろその方がメリットが大きい
* **HTML要素とほぼ同じ感覚で、idやclassを振ってCSSを適用したりjQueryで操作したりできる**
  * だから、簡単に不定形な要素をCSSでアニメーションさせたり、jQueryでクラスを付けたり外したりできる
* CSSアニメーションが必要ないなら、IE9から使える
* XMLファイルなので、**画像なのにバージョン管理システムとの相性が良い**
* `<defs>`と`<use>`による再利用の仕掛けが強力
* これまで透過PNGくらいでしか扱えなかった不定形要素のデザインが扱いやすくなる

**画像というよりは、新しく増えたHTML要素の一種**だと思った方がイメージしやすいのではないかと思う。

# こんな使い方が便利そう

イラレで書き出したものをそのまま`<img>`要素で使うよりも、内容をインラインでHTMLに書いて使う方がSVGのメリットを生かせる。

1. Illustrator上で要素をデザインする
2. 全ての要素をアウトライン化する
2. SVGへエクスポートする。設定はこんな感じ![svg-setting.png](https://qiita-image-store.s3.amazonaws.com/0/48238/d8329d75-b09a-dfc8-b60b-eaa694630b2f.png)
3. [svgo-gui](https://www.google.co.jp/search?q=svgo-gui)でコードをスリム化する
  * 容量削減というより、可読性を高める効果が大きい
4. テキストエディタでコードを開き、HTMLにコピペする
  * 要素は数えるほどしか残っていないはずなので、どのコードが何の形状なのかはだいたい分かるようになる
  * `<svg>`要素の`viewBox`属性は、意味を理解するまでは消してしまっても良いかも
5. 操作したい要素に`id`か`class`を振り、後はJSやCSSで煮るなり焼くなり
6. 慣れてきたら自分で要素を手書きで足してみたり、属性値を変更したり

# ちょっとだけ普段と違うところ

## CSSは全部が使える訳ではない

SVGで使えるCSSは、HTMLのCSSと比べて若干仕様が違う。

## SVG要素に対してjQueryの `addClass()`、`removeClass()`は効かない

`$('g').addClass('show')`とかはできない。変わりに`attr()`を使う。

```js
// .showを付ける
$('g').attr('class', 'show');
// クラスを空に
$('g').attr('class', null);
```

# 知っとくと便利なSVGのタグ

## `<g>`

`<div>`みたいな感じで、複数の形状をグループ化してまとめて操作したりできる。複数の要素をまとめてアニメーションさせたりするのに便利。

## `<defs>`と`<use>`

`<defs>`タグの内側に書いた要素は、別の`<use>`タグで参照できる。これにより、サイト全体で使用するSVG要素を外部ファイルにまとめ、好きなページで使いまわすことができる。

IE系や一部のブラウザは外部SVGの参照に未対応だが、polyfillしてくれるライブラリが存在する。
https://jonathantneal.github.io/svg4everybody/

```xml:graphics.svg

<svg xmlns="http://www.w3.org/2000/svg">
  <defs>
    <g id="company-logo">
      <path d="..." />
      <path d="..." />
      <path d="..." />
    </g>
    <path id="department-logo" d="..." />
  </defs>
</svg>

```
```html:index.html

<html>
...
<header class="site-header">
  <div class="logo">
    <svg xmlns="http://www.w3.org/2000/svg">
      <!-- 外部SVGの#company-logo を参照 -->
      <use id="logo1" xlink:href="/images/graphics.svg#company-logo" />
    </svg>
  </div>
</header>
...
<article>
  <div class="department-content">
    <svg xmlns="http://www.w3.org/2000/svg">
      <!-- 外部SVGの#department-logo を参照 -->
      <use id="logo2" xlink:href="/images/graphics.svg#department-logo" />
    </svg>    
  </div>
</article>
...
</html>
```

# 参考サイト

日本語のドキュメントも充実してきているので、分からないことがあっても結構調べられた。

* [svg要素の基本的な使い方まとめ](http://www.h2.dion.ne.jp/~defghi/svgMemo/svgMemo_05.htm)
  * ここさえ読めばほとんどのことはできそうなくらいよくまとまっているページ。しかも日本語
* [マークアップ・エンジニアのためのSVG入門 - SVGコードの基本 | CodeGrid](https://app.codegrid.net/entry/svg-basic)
* [SVGアニメーションの現状 | プログラミング | POSTD](http://postd.cc/the-state-of-svg-animation/)
  * 本稿では触れていない、SVG独自のアニメーション表現が紹介されている
* [見た目のクオリティはそのままで、SVGファイルを大幅に軽量化する便利ツール -SVGO GUI | コリス](http://coliss.com/articles/build-websites/operation/design/optimizing-svg-files-svgo-gui.html)