【SVG画像】1つの画像ファイルで複数の色違い画像を使いまわす


SVG画像はコードになってるので、HTMLにそれを直接書けば、CSSで色を変えたり、JSでアニメーションさせたりできるがコードが長いし、HTMLが見づらくなってしまう。

なにかスッキリかく方法はないのかと探して見つけたのが、`Useタグ`で読み込ませる方法です！

# 


# まずSVG画像のコードを編集する

```html:icon-star.svg（編集前）
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M8.30148 ... 11.8421Z" stroke="black" />
</svg>
```
```html:sample.svg（編集後）
<svg xmlns="http://www.w3.org/2000/svg">
  <symbol id="star" viewBox="0 0 16 16">
    <path d="M8.30148 ... 11.8421Z"/>
  </symbol>
</svg>

```

1. コード内の `fill`や`storoke` 指定のような装飾の指定を削除
CSSで指定するため、コード内に指定があると反映されないため
2. `<path>`（画像の部分） を `<symbol>` で囲む
`<symbol>`の中身がHTMLで呼び出されます。
3. `<svg>`の width、height 指定を削除
こちらもCSSで指定
4. `<svg>`の `viewbox`指定を`<symbol>`に指定
5. `<symbol>`に idを指定
HTML側でIDを指定して呼び出します

# HTMLに`<use>`でSVGを呼び出し、使い回す
```html:index.html
<svg class="c-icon">
  <use xlink:href="../img/icon-star.svg#star"></use>
</svg>

<svg class="c-icon c-icon--blue">
  <use xlink:href="../img/icon-star.svg#star"></use>
</svg>

<svg class="c-icon c-icon--24">
  <use xlink:href="../img/icon-star.svg#star"></use>
</svg>

<svg class="c-icon c-icon--outline">
   <use xlink:href="../img/icon-star.svg#star"></use>
</svg>
```
1. クラス名は`<svg>`に指定します
2. `<use>`の`xlink:href`に**SVG画像へのパス+SVG画像の`<symbol>`のIDを指定**します

これでSVGが呼び出されます！
ただ色とサイズを指定してないので表示されないのでCSSで指定します。

# CSSで色とサイズを追加する
```scss:style.scss
.c-icon {
  margin-right: 8px;
  width: 16px;
  height: 16px;
  vertical-align: middle;

  fill: black;

  &--blue {
    fill: blue;
  }

  &--24 {
    width: 24px;
    height: 24px;
  }
  &--outline {
    stroke: black;
    fill: transparent;
  }
}
```
色とサイズ違いを1つのSVG画像で使いまわしが可能になりました。
strokeの指定でアウトラインのスタイルも作れます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304162/8af340e2-c053-a250-e956-9439be4a730f.png)




# SVG画像コードを外部ファイルにしなくても可能
HTML内に呼び出すSVGコードを書いても使い回すことができます。
```html:index.html
<!-- 呼び出すSVGコード -->
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="star" viewBox="0 0 16 16">
    <path d="M8.09082 ... 12.4226Z" />
  </symbol>
</svg>

<!-- useタグで上のSVGを呼び出す -->
<svg class="c-icon c-icon--red">
  <use xlink:href="#star"></use>
</svg>
<svg class="c-icon c-icon--blue">
  <use xlink:href="#star"></use>
</svg>
```
この場合は`<use>`の`xlink:href`で画像パスを書かず、IDだけ指定すればOK

# codepen
外部ファイルは色々試しましたがSVGだからかcodepenでうまく読み込んでくれませんでした...
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="gOoJjwa" data-user="himeka223" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/himeka223/pen/gOoJjwa">
  Untitled</a> by himeka223 (<a href="https://codepen.io/himeka223">@himeka223</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 会社のロゴで遊んでみた

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="qBpzNeW" data-user="himeka223" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/himeka223/pen/qBpzNeW">
  Untitled</a> by himeka223 (<a href="https://codepen.io/himeka223">@himeka223</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

strokeは色々できて楽しそう

https://www.webcreatorbox.com/tech/svg-stroke

# 互換性について
## IE11では`<use>`の**外部ファイル呼び出し**が未対応
対応としては外部ファイルで呼び出さず、同じファイル内にSVGコードを書けば問題なく使えます。
でもIEのためだけにHTML内に画像を記載するのも嫌だし、IEのために特別な指定をするのもなんか...
IE対応する場合はimgで読み込ませるのが一番いいのかもしれないです


## iOS 9.3では、`<use>`はキャッシュされない
リロードのたびに読み込まれるので重い...
iOS 9.3、流石に古いので使う人ほぼいないのではと。
参考：[【随時更新】iOS バージョン別シェアを発表。日本国内のシェア・全体の推移は？](https://moduleapps.com/mobile-marketing/ios-ver/)

# まとめ
複雑そうで避けてきたSVGだけど1色の色変えなら簡単にできそう！
テンプレのページの色変えや、アイコンのホバーなどで使える機会が増えそうです

# 参考

https://qiita.com/mzzzk/items/8bb2623d78c8444bbbef