SVGを色ごとに書き出すとファイルが増殖して管理が大変。できればCSSだけで色を差し替えたい——でも color
や fill
を指定しても色が変わらないことがある。
本記事はその「なぜ?」を解決します。XDから書き出したSVGがCSSで色を受け付けにくい理由(直書きfill
/stroke
問題)をまず整理。次に、単色=currentColor
化、多色=CSS変数、そしてスプライト(<symbol>
→<use>
)まで、現場で詰まらない最短手順に絞って解説します。
1) なぜCSSで色が変わらない?

たとえば、こういうアイコンをXDからSVGとして書き出し、SVGをテキストファイルで開いたコードをHTMLファイルに貼り付けます。
このSVGにcolor:redを指定してみます。
<div class="svg-wrap">
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 17 17">
<g transform="translate(-4 -4)">
<path d="M6-1A7,7,0,1,1-1,6,7.008,7.008,0,0,1,6-1ZM6,11A5,5,0,1,0,1,6,5.006,5.006,0,0,0,6,11Z" transform="translate(5 5)" fill="#758ce9" />
<path d="M20,21a1,1,0,0,1-.707-.293l-4.2-4.2a1,1,0,1,1,1.414-1.414l4.2,4.2A1,1,0,0,1,20,21Z" fill="#758ce9" />
</g>
</svg>
</div>
.svg-wrap svg {
color: red
}
しかし、色は変わらない。。。
それは、SVGに指定されているこの部分が原因です。
fill="#758ce9"
fill="#758ce9"
fill
は SVG の「塗りつぶし色」を指定する属性/プロパティです。
パスや図形の内側を何色で塗るかを決めます(輪郭の色は stroke
)。
XDは書き出し時に各要素へ fill="#xxxxxx"
/ stroke="#xxxxxx"
を要素属性として直書きします。
この直書きは親の color
や fill
の継承より優先度が高いため、CSS指定が負けるのが原因です。
2) 単色アイコンの正解:currentColor
に置換(最短・安定)
やることは1つ。書き出し後の fill
/stroke
を currentColor
に置換します。
以後は親の color
だけで色変更が可能です。
<div class="svg-wrap">
<svg xmlns="http://www.w3.org/2000/svg" width="17" height="17" viewBox="0 0 17 17">
<g transform="translate(-4 -4)">
<path d="M6-1A7,7,0,1,1-1,6,7.008,7.008,0,0,1,6-1ZM6,11A5,5,0,1,0,1,6,5.006,5.006,0,0,0,6,11Z" transform="translate(5 5)" fill="currentColor" />
<path d="M20,21a1,1,0,0,1-.707-.293l-4.2-4.2a1,1,0,1,1,1.414-1.414l4.2,4.2A1,1,0,0,1,20,21Z" fill="currentColor" />
</g>
</svg>
</div>
.svg-wrap.svg-wrap--red {
color: red
}
.svg-wrap.svg-wrap--green{
color: green
}
.svg-wrap.svg-wrap--blue{
color: blue
}
書き出し後の
fill
/stroke
をcurrentColor
に置換しよう。
3) 多色アイコンの正解:CSS変数でパーツ分離

次にこういう複数色のアイコンはどうでしょうか?
書き出し直後のSVGはこのようになっていました。
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="18.5" viewBox="0 0 28 18.5">
<g id="icon-car-multicolor_2_" data-name="icon-car-multicolor (2)" transform="translate(-2 -3)">
<path id="パス_1" data-name="パス 1" d="M6,10.5,9.2,5.4A4,4,0,0,1,12.6,3h6.8a4,4,0,0,1,3.4,2.4L26,10.5h2a2,2,0,0,1,2,2V18a3,3,0,0,1-3,3H5a3,3,0,0,1-3-3V12.5a2,2,0,0,1,2-2Z" fill="#334155"/>
<path id="パス_2" data-name="パス 2" d="M9.5,10.5l2-4a2,2,0,0,1,1.8-1.2h5.3a2,2,0,0,1,1.8,1.2l2,4Z" fill="#93c5fd"/>
<circle id="楕円形_1" data-name="楕円形 1" cx="2" cy="2" r="2" transform="translate(8 17.5)" fill="#0f172a"/>
<circle id="楕円形_2" data-name="楕円形 2" cx="2" cy="2" r="2" transform="translate(20 17.5)" fill="#0f172a"/>
<rect id="長方形_1" data-name="長方形 1" width="2.2" height="1.8" rx="0.4" transform="translate(26.5 14)" fill="#fbbf24"/>
</g>
</svg>
多色のSVGは各パーツにクラス名を付けて、色はCSS側で与えるやり方をご紹介します。
XD書き出し直後は fill="#xxxxxx"
が直書きされていますが、今回はそちらをすべて、削除し、SVGにクラスを振って、CSSで色を当てています。
<div class="car car--sky">
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="18.5" viewBox="0 0 28 18.5" aria-hidden="true">
<g transform="translate(-2 -3)">
<path class="car__body" d="M6,10.5,9.2,5.4A4,4,0,0,1,12.6,3h6.8a4,4,0,0,1,3.4,2.4L26,10.5h2a2,2,0,0,1,2,2V18a3,3,0,0,1-3,3H5a3,3,0,0,1-3-3V12.5a2,2,0,0,1,2-2Z"/>
<path class="car__window" d="M9.5,10.5l2-4a2,2,0,0,1,1.8-1.2h5.3a2,2,0,0,1,1.8,1.2l2,4Z"/>
<circle class="car__wheel" cx="2" cy="2" r="2" transform="translate(8 17.5)"/>
<circle class="car__wheel" cx="2" cy="2" r="2" transform="translate(20 17.5)"/>
<rect class="car__light" width="2.2" height="1.8" rx="0.4" transform="translate(26.5 14)"/>
</g>
</svg>
</div>
.car--sky .car__body { fill:#0ea5e9; }
.car--sky .car__window { fill:#bae6fd; }
.car--sky .car__wheel { fill:#1e293b; }
.car--sky .car__light { fill:#fde68a; }
まとめ
- XDの出力はそのままでOK。後処理で色直書きを外すのが最短・安定。
- 単色=
currentColor
、多色=CSS変数に寄せれば、配色変更がCSSだけで完結。