chlonolog

web, digital gadgets, and more.

background-imageとして使用しているSVGの色を変更したい

webフォントを使用するように、SVG画像をCSSの:before:afterで使用したいときがあります。
しかしSVG画像をbackground-image:で使用すると、webフォントのようにcolor:#XXXXXX;で色を変更することができません。

なんとかならないかと調べた結果、CSS内にSVG画像を直接取り込んで色を変更する方法を見つけたので、取り入れてみました。


画像を作る

当サイトのTwitterへのリンクでは、Twitter公式のBrand Resourcesで入手したアイコンの横に矢印を追加したものを使用しています。
22px×14pxの実寸で作成してあります。Inkspaceで編集し、svgo-guiで最適化しました。

10倍に拡大すると、こんな感じです。のちの作業を楽にするため、アイコンと矢印は別の色にしてあります。

SVGなので、拡大しても綺麗ですね。
ちなみに、エディタで開くとこんな感じ。

<svg xmlns="http://www.w3.org/2000/svg" width="22" height="14">
  <path d="M3.148 10.757l-.009-2.788-3.028.092-.04-2.054 3.069-.092v-2.713h.017l4.537 3.771v.026l-4.546 3.762z"/>
  <path d="M21.712 2.717c-.515.228-1.069.383-1.65.452.593-.355 1.048-.918 1.263-1.589-.555.329-1.17.568-1.824.697-.524-.558-1.27-.907-2.097-.907-1.586 0-2.872 1.286-2.872 2.872 0 .225.025.444.074.655-2.387-.12-4.504-1.263-5.92-3.001-.247.424-.389.918-.389 1.444 0 .997.507 1.876 1.278 2.391-.471-.015-.914-.144-1.301-.359v.036c0 1.392.99 2.552 2.304 2.816-.241.066-.495.101-.757.101-.185 0-.365-.018-.54-.052.366 1.141 1.426 1.972 2.683 1.995-.983.77-2.221 1.23-3.567 1.23-.232 0-.46-.014-.685-.04 1.271.815 2.781 1.291 4.403 1.291 5.283 0 8.172-4.377 8.172-8.172l-.008-.372c.561-.405 1.048-.911 1.433-1.487z" fill="#1da1f2"/>
</svg>

SVG画像のコードをurlエンコードして出力する

こちらの回答のうち、使い回しが容易な4番目の方のコードをいただきました。
str-replace()url-encode()は内部処理で使用しており、SCSS内で画像使用の際呼び出すのはinline-svg()です。

この処理と実際に画像を埋め込む部分の処理は、「_svg.scss」というファイルにまとめてあります。

/**
 * SVG画像をアイコンに使いたい的ないろいろ
 *
 *  [Html] SVG塗りつぶしの色をBackground-Imageとして扱うときに変更する
 * https://code.i-harness.com/ja/q/cbfa3c
 */
@function str-replace($string, $search, $replace: '') {
  $index: str-index($string, $search);
  @if $index {
    @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
  }
  @return $string;
}
@function url-encode($string) {
  $map: (
    "%": "%25",
    "<": "%3C",
    ">": "%3E",
    " ": "%20",
    "!": "%21",
    "*": "%2A",
    "'": "%27",
    '"': "%22",
    "(": "%28",
    ")": "%29",
    ";": "%3B",
    ":": "%3A",
    "@": "%40",
    "&": "%26",
    "=": "%3D",
    "+": "%2B",
    "$": "%24",
    ",": "%2C",
    "/": "%2F",
    "?": "%3F",
    "#": "%23",
    "[": "%5B",
    "]": "%5D"
  );
  $new: $string;
  @each $search, $replace in $map {
    $new: str-replace($new, $search, $replace);
  }
  @return $new;
}

@function inline-svg($string) {
  @return url('data:image/svg+xml;utf8,#{url-encode($string)}');
}

SVG画像をコード内に埋め込む

上で実装したコードを、こちらで呼び出しています。

SVGの部分は、<path>fill="#1da1f2"のついている方がTwitterアイコン、ついていない方が矢印です。
それぞれに変数を埋め込んで、自在に色を変えられるようにしました。
アイコンの<path>の末尾についていたfill=#XXXXXXは、見やすくなるよう先頭へ移動してあります。矢印の方にはfillの指定自体ありませんでしたので、新たに追加ししました。

デフォルトでは、両方ともTwitterのブランドカラーで染まります。

/**
 * Twitterのアイコン
 * hrefが「https://twitter.」で始まるURLにつける
 */
 @mixin goto-twitter($color:'#1da1f2', $allow-color: $color) {
  width: 21px;
  height: 14px;
  background-image: inline-svg(
    '<svg xmlns="http://www.w3.org/2000/svg" width="22" height="14">'
    + '<path fill="' + $allow-color + '" d="M3.148 10.757l-.009-2.788-3.028.092-.04-2.054 3.069-.092v-2.713h.017l4.537 3.771v.026l-4.546 3.762z"/>'
    + '<path fill="' + $color + '" d="M21.712 2.717c-.515.228-1.069.383-1.65.452.593-.355 1.048-.918 1.263-1.589-.555.329-1.17.568-1.824.697-.524-.558-1.27-.907-2.097-.907-1.586 0-2.872 1.286-2.872 2.872 0 .225.025.444.074.655-2.387-.12-4.504-1.263-5.92-3.001-.247.424-.389.918-.389 1.444 0 .997.507 1.876 1.278 2.391-.471-.015-.914-.144-1.301-.359v.036c0 1.392.99 2.552 2.304 2.816-.241.066-.495.101-.757.101-.185 0-.365-.018-.54-.052.366 1.141 1.426 1.972 2.683 1.995-.983.77-2.221 1.23-3.567 1.23-.232 0-.46-.014-.685-.04 1.271.815 2.781 1.291 4.403 1.291 5.283 0 8.172-4.377 8.172-8.172l-.008-.372c.561-.405 1.048-.911 1.433-1.487z"/>'
    + '</svg>');
}

SASS内で呼び出す

以上の設定で、呼び出し時に色を指定できるようになりました。

@import "svg";

$svg-base-color: #666;

//外部リンク
a[target="_blank"] {
//特定のサイトへのリンク
  &[href^='https://twitter.'] {
    &:after {
      position: relative;
      display: inline-block;
      top: .2em;
      margin: 0 .2em 0 .15em;

      // 全体的にグレーにする
      @include goto-twitter('#aaa');
    }
    &:hover:after {
      // 矢印だけグレーにする
      // アイコン部分はデフォルトのブランドカラーになる
      @include goto-twitter($allow-color: '#aaa');
    }
  }
}

感想

今回は:before:afterに使用しましたが、「背景に適用して、ページの内容ごとに色を変更する」なんて使い方もできそうですね。

SVG画像を絡めた処理は初めてやったのですが、思っていたよりも簡単で「これは便利だ!」と感じました。
画像なのにテキストエディタで開けるなんて、なんだか不思議で新鮮です。

コメント

© 2018 chlono