♻️

svg画像の色変え・再利用をする方法

2023/10/03に公開

前置き

  • svg画像の呼び出しや色変えが簡単に行えるか(柔軟性)
  • コード内での視認性に問題がないか(視認性)
  • コンパイル時に画像が重複しないか(重複)

上記3点を主な採用基準として記述しています。

個人・チームで管理のしやすい方法が一番いいと思います。
重複はちょうふく派です。

画像として使う

柔軟性 視認性 重複
× する

一番確実で簡単。
jpgやpngのようにフォルダにsvg画像を置いてパスを埋め込む方法です。
色変えをするには、色を変えたsvg画像をそれぞれ用意する必要があります。

HTMLにインラインで埋め込む

柔軟性 視認性 重複
しない(△)
<svg width="1200" height="90" viewBox="0 0 1200 90" fill="none" display="none" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <path id="wave" d="M0 90V18C100 -6 200 -6 300 18C400 42 500 42 600 18C700 -6 800 -6 900 18C1000 42 1100 42 1200 18V90H0Z"></path>
  </defs>
  <use xlink:href="#wave"></use>
</svg>

<!-- 同じページ内の別のsvgタグから呼び出し -->
<svg width="1200" height="90" viewBox="0 0 1200 90" xmlns="http://www.w3.org/2000/svg">
  <use xlink:href="#wave"></use>
</svg>

柔軟性
defsタグで囲った部分のsvgは表示されなくなり、useタグにシンボルのidを指定することで画像を呼び出すことができます。
同じページ内なら別のsvgタグを定義して、そこから呼び出すこともできます。

色変え
fill属性を使えばインラインで色変えができる他、classやidをuseタグに付け足して、cssで色変えすることもできます。

視認性
インラインでsvgを書き込むことで、コードの視認性が下がりやすいです。

重複
通常のHTMLコーディングだと、別のページでは再度defsを宣言する必要があり、重複が発生します。

コンポーネントとして使う

柔軟性 視認性 重複
しない

HTMLにインラインで埋め込む弱点を完全に克服したのが、javaScriptフレームワークや外部ファイルのインポートを用いることで、コンポーネントとしてsvgを使用する方法です。
vue.jsのクイックスタートでも採用されています。

Icon.vue
<template>
  <!-- fill="currentColor"にはbodyのcolorが入る -->
  <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
    <path
      d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
    />
  </svg>
</template>
index.vue
<script setup>
// インポート
import Icon from "./Icon.vue";
</script>

<template>
  <!-- 表示 -->
  <Icon fill="#ffff00" />
</template>

同じようにインライン、CSSで色変えができて、コンパイル時の重複もありません。

SCSSでmixinとして使う

柔軟性 視認性 重複
する

コンパイルした際のコードの重複さえ気にならなければ便利に使用できます。
また、CSSの書き方次第では画像として使うのと同じレベルまで重複を抑えられます。
今後ブラウザではscssをコンパイルせずに読み込めるようになるらしいので、そうなったときには遠慮なく使用できます。

_variables.scss

@mixin icon_arrow($color: "fff") {// 初期値は#fff
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="12.196" height="8.356" viewBox="0 0 12.196 8.356"><path d="M7.982,0,6.767,1.216l2.1,2.1H0V5.038H8.932l-2.115,2.1,1.21,1.22,2.951-2.929,0,0,.607-.607.608-.6,0,0,0,0-.607-.607L10.986,3l0,0Z" fill="%23#{$color}"/></svg>');
  // fill="%23#{$color}"は「#を%エンコーディングした値(%23)」と「scss変数の埋め込み(#{$color})」で構成されている
  background-repeat: no-repeat;
  background-position: center right min(5vw, 25px);
  background-size: 12px;
  transition: 0.2s;

  &:hover {
    background-position: center right min(4.5vw, 20px);
  }
}

a {
  @include icon_arrow("24489B");// 呼び出す際にはカラーコードからハッシュを省く
}

色変え
mixinに変数を複数設定することで複数個所の色を別々に変えることができます。

柔軟性
共通宣言用のscssにまとめて宣言しておけば、どのscssからでも呼び出せます。

@use "variables" as *;

視認性
一か所にまとめて宣言することで視認性を保てます。
呼び出す際も変数名で検索しやすいです。

重複
cssにコンパイルした際に、呼び出したinclueの数だけハードコーディングされます。
結果として、画像として利用するよりもサイズが大きくなる可能性があります。
自由度とトレードオフです。

Discussion