わすれたあかんえ

Railsのviewにデザインを組み込む人のつぶやき。にわかカープファン。

SVGのオブジェクトごとにCSSで色を切り替える

f:id:asachun1209:20160324180832p:plain

デザインpsdを見ながらhtmlでコーディングするとき、たくさん画像を書き出しますよね。 たとえばpngのアイコンを作る場合、形が同じでも色が違えばpngファイルをたくさん書きださなければいけません。色だけ変えたものをひとつずつ、@2xサイズも用意してちまちまと……書き出して……

やってらんないっすよ!

せめて、形が同じなら使いまわしたい……

そう!SVGを使えば、同じオブジェクトを使ってCSSで色だけ変えたものを量産できるのです!

「それだったらwebフォントでいいじゃん」と思われるかもしれませんが、webフォントはアイコンひとつにつき1色しか使えませんよね?SVGでやればアイコンひとつでも複数色使うことができます。

f:id:asachun1209:20160220154000p:plain:w250

このSVGアイコンを使いまわして、

f:id:asachun1209:20160323203804p:plain

こんなかんじでカラフルなアイコンを量産しますよー!

ベクターでアイコンを作成

アイコン作るのがめんどくさい人はicomoonから適当なアイコンを見つくろってDLしましょう。 プロジェクトを新規作成し、フッタの「Selection」からお好みのアイコンをクリックし、「Generate SVG & More」からDLします。

今回はicomoonからDLした場合の手順を説明します。

DLしたアイコンを調整する

今回はこちらの吹き出しがふたつ重なったアイコンを使用します。

f:id:asachun1209:20160220154000p:plain:w250

まずicomoonからDLした状態のままだと、オブジェクトごとに分かれていない場合があるのでその場合はIllustratorで編集します。

<?xml version="1.0" encoding="utf-8"?>
<!-- Generated by IcoMoon.io -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34" height="32" viewBox="0 0 34 32">
<path d="M25.132 13.165c0-5.165-5.627-9.352-12.566-9.352s-12.566 4.187-12.566 9.352c0 3.104 2.032 5.854 5.16 7.555-0.009 0.027-2.492 4.545-2.492 4.545s7.582-2.892 7.603-2.904c0.744 0.103 1.511 0.155 2.295 0.155 6.939 0 12.566-4.187 12.566-9.351zM34.385 16.087c0-5.164-5.297-9.314-11.031-9.351 8.22 8.188-1.461 16.912-9.351 16.912 0 0 0.877 1.79 7.816 1.79 0.783 0 1.551-0.054 2.295-0.156 0.021 0.014 7.604 2.904 7.604 2.904s-2.484-4.517-2.492-4.544c3.127-1.701 5.159-4.452 5.159-7.555z"></path>
</svg>

path要素が実際のオブジェクトを表すのですが、こちらはふたつの吹き出しがひとつのオブジェクトになっているので、ふたつのオブジェクトに分けます(もともと分かれていたり、自分で作成する場合は「SVGファイルをエディタで編集」のステップまで飛ばしていただいてOKです)。

ちなみにオブジェクトはpath要素だけでなく、rect要素やcircle要素などさまざまなものがあるので、わからないときはW3Cのドキュメントを見て調べてみてください。

Illustratorで編集

オブジェクトを選択し、「オブジェクト」→「複合パス」→「解除」を選択します。

f:id:asachun1209:20160220152959p:plain

ちなみにオブジェクトが複合パスかどうかはレイヤーパネルを開き、左の▼アイコンをクリックするとわかります。

f:id:asachun1209:20160220153326p:plain

ちなみに複合パスを解除した後はこんなかんじになります。ふたつのオブジェクトに分かれていますね!

f:id:asachun1209:20160220153420p:plain

SVGで保存

「別名で保存」から「ファイル形式:SVG」を選択して保存します。 SVG保存設定はこんなかんじです。f:id:asachun1209:20160220153634p:plain:w500

SVGファイルをエディタで編集

保存したSVGをお好きなエディタで開きます。私はSublime Textを使っています。

Illustratorで保存したままの状態だと余計なコードがついてるので削除します。

保存したままの状態↓

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
     y="0px" width="34px" height="32px" viewBox="0 0 34 32" enable-background="new 0 0 34 32" xml:space="preserve">
<path d="M25.1,13.2c0-5.2-5.6-9.4-12.6-9.4S0,8,0,13.2c0,3.1,2,5.9,5.2,7.6c0,0-2.5,4.5-2.5,4.5s7.6-2.9,7.6-2.9
  c0.7,0.1,1.5,0.2,2.3,0.2C19.5,22.5,25.1,18.3,25.1,13.2z"/>
<path d="M34.4,16.1c0-5.2-5.3-9.3-11-9.4c8.2,8.2-1.5,16.9-9.4,16.9c0,0,0.9,1.8,7.8,1.8c0.8,0,1.6-0.1,2.3-0.2c0,0,7.6,2.9,7.6,2.9
  s-2.5-4.5-2.5-4.5C32.4,21.9,34.4,19.2,34.4,16.1z"/>
</svg>

余計なコードを削除した状態↓

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34px" height="32px" viewBox="0 0 34 32">
<path d="M25.1,13.2c0-5.2-5.6-9.4-12.6-9.4S0,8,0,13.2c0,3.1,2,5.9,5.2,7.6c0,0-2.5,4.5-2.5,4.5s7.6-2.9,7.6-2.9
  c0.7,0.1,1.5,0.2,2.3,0.2C19.5,22.5,25.1,18.3,25.1,13.2z"/>
<path d="M34.4,16.1c0-5.2-5.3-9.3-11-9.4c8.2,8.2-1.5,16.9-9.4,16.9c0,0,0.9,1.8,7.8,1.8c0.8,0,1.6-0.1,2.3-0.2c0,0,7.6,2.9,7.6,2.9
  s-2.5-4.5-2.5-4.5C32.4,21.9,34.4,19.2,34.4,16.1z"/>
</svg>

すっきりしましたね。

注意点

ちなみに、このときpath要素などのオブジェクトにfill属性がついていると、CSSで色を変えられなくなってしまうので注意してください!色が変わらないことが決まっている場合は大丈夫ですが、今回は色を変えたいので消してしまいましょう。

オブジェクトをg要素で囲む

g要素とはオブジェクトをグループ化するための要素です。g要素でオブジェクトを囲んでクラスをつけることで、CSSからg要素を操作できるようになります。

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="34px" height="32px" viewBox="0 0 34 32">
  <symbol id="IconComments">
    <g id="#IconComments-back">
      <path d="M25.1,13.2c0-5.2-5.6-9.4-12.6-9.4S0,8,0,13.2c0,3.1,2,5.9,5.2,7.6c0,0-2.5,4.5-2.5,4.5s7.6-2.9,7.6-2.9
        c0.7,0.1,1.5,0.2,2.3,0.2C19.5,22.5,25.1,18.3,25.1,13.2z"/>
    </g>
    <g id="IconComments-front">
      <path d="M34.4,16.1c0-5.2-5.3-9.3-11-9.4c8.2,8.2-1.5,16.9-9.4,16.9c0,0,0.9,1.8,7.8,1.8c0.8,0,1.6-0.1,2.3-0.2c0,0,7.6,2.9,7.6,2.9
        s-2.5-4.5-2.5-4.5C32.4,21.9,34.4,19.2,34.4,16.1z"/>
    </g>
  </symbol>
</svg>

まず、path要素をg要素で囲みます。↑のコードではそのg要素2つをさらにsymbol要素で囲んでいます(symbol要素で囲むのは、参照するための要素として定義するためです)。今回このSVGコードは別の場所から参照します。

これでSVGファイルの準備が整いました!次から実際にCSSでオブジェクトごとに色を切り替えます。

インラインSVGで記述

SVGimg要素やobject要素で読み込むことができますが、今回解説する方法はインラインSVGで記述する必要があります。 なのでhtmlに直接SVGコードを書きます。

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no' name='viewport'>
    <title>SVGテスト</title>
    <link href="/stylesheets/application.css" rel="stylesheet" />
  </head>
  <body>
    <!-- htmlに直接svgを書く -->
    <svg class='SvgIcon' viewbox='0 0 205.2 145.4' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns='http://www.w3.org/2000/svg'>
      <symbol id='IconComments'>
        <title>comments</title>
        <g id='IconComments-back'>
          <path d='M150,55.8C150,25,116.4,0,75,0C33.6,0,0,25,0,55.8c0,18.5,12.1,34.9,30.8,45.1c-0.1,0.2-14.9,27.1-14.9,27.1&#x000A; s45.2-17.3,45.4-17.3c4.4,0.6,9,0.9,13.7,0.9C116.4,111.6,150,86.6,150,55.8L150,55.8z'></path>
        </g>
        <g id='IconComments-front'>
          <path d='M205.2,73.2c0-30.8-31.6-55.6-65.8-55.8c49.1,48.9-8.7,100.9-55.8,100.9c0,0,5.2,10.7,46.6,10.7c4.7,0,9.3-0.3,13.7-0.9&#x000A;  c0.1,0.1,45.4,17.3,45.4,17.3s-14.8-27-14.9-27.1C193.1,108.2,205.2,91.8,205.2,73.2L205.2,73.2z'></path>
        </g>
      </symbol>
    </svg>
  </body>
</html>
.SvgIcon {
  position: absolute;
  width: 0;
  height: 0; 
}

上記のSVGは直接描画したくないので、CSSで非表示にしておきます。ちなみに非表示にするのにdisplay: none;を使用するとグラデーションなどは打ち消されてしまうため、それ以外の方法で非表示にしたほうがベターです。

そして定義したSVGを使い回すため、新たなsvg要素の中にuse要素を追加します。

<!DOCTYPE html>
<html>
  <head>
    <meta charset='utf-8'>
    <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no' name='viewport'>
    <title>SVGテスト</title>
    <link href="/stylesheets/application.css" rel="stylesheet" />
  </head>
  <body class='index'>
    <svg class='SvgIcon' viewbox='0 0 205.2 145.4' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns='http://www.w3.org/2000/svg'>
      <symbol id='IconComments'>
        <title>comments</title>
        <g id='IconComments-back'>
          <path d='M150,55.8C150,25,116.4,0,75,0C33.6,0,0,25,0,55.8c0,18.5,12.1,34.9,30.8,45.1c-0.1,0.2-14.9,27.1-14.9,27.1&#x000A; s45.2-17.3,45.4-17.3c4.4,0.6,9,0.9,13.7,0.9C116.4,111.6,150,86.6,150,55.8L150,55.8z'></path>
        </g>
        <g id='IconComments-front'>
          <path d='M205.2,73.2c0-30.8-31.6-55.6-65.8-55.8c49.1,48.9-8.7,100.9-55.8,100.9c0,0,5.2,10.7,46.6,10.7c4.7,0,9.3-0.3,13.7-0.9&#x000A;  c0.1,0.1,45.4,17.3,45.4,17.3s-14.8-27-14.9-27.1C193.1,108.2,205.2,91.8,205.2,73.2L205.2,73.2z'></path>
        </g>
      </symbol>
    </svg>

    <!-- svg要素の中にuse要素 -->
    <svg class='Svg01'>
      <!-- use要素のxlink属性で先ほど定義したg要素を参照。use要素にクラスを指定しておきます -->
      <use class='Svg01-front' xlink:href='#IconComments-front'></use>
      <use class='Svg01-back' xlink:href='#IconComments-back'></use>
    </svg>
  </body>
</html>

f:id:asachun1209:20160323211959p:plain:w250

ブラウザで開くとこんなかんじで表示されていると思いますー。 ここから楽しい楽しいスタイリングですよ?

CSSでスタイリング

use要素にクラスをつけたので、普通にクラスを指定してCSSを装飾していきます。 SVGの場合はfill属性に色を指定します。

.Svg01-front {
  fill: #42AFE3; 
}
.Svg01-back {
  fill: #97CD76; 
}

f:id:asachun1209:20160323212506p:plain:w250

じゃーん! カラフルになりましたね。

同じように量産していけば……

<svg class='Svg01'>
  <use class='Svg01-front' xlink:href='#IconComments-front'></use>
  <use class='Svg01-back' xlink:href='#IconComments-back'></use>
</svg>
<svg class='Svg02'>
  <use class='Svg02-front' xlink:href='#IconComments-front'></use>
  <use class='Svg02-back' xlink:href='#IconComments-back'></use>
</svg>
<svg class='Svg03'>
  <use class='Svg03-front' xlink:href='#IconComments-front'></use>
  <use class='Svg03-back' xlink:href='#IconComments-back'></use>
</svg>
.Svg01-front {
  fill: #42AFE3; 
}
.Svg01-back {
  fill: #97CD76; 
}

.Svg02-front {
  fill: #97CD76; 
}
.Svg02-back {
  fill: #FCE473; 
}

.Svg03-front {
  fill: #ED6C63; 
}
.Svg03-back {
  fill: #42AFE3; 
}

f:id:asachun1209:20160323203804p:plain

じゃじゃじゃーん! いろんなカラーバリエーションのアイコンができました。

しかもSVGなので、Retineディスプレイでも綺麗です!@2xや@3xで書き出す必要もありませんやったね!

たとえば、デザインテーマごとにアイコンの形は一緒だけど色だけ変わる、みたいなときに大変便利です。 試してみてください〜