デザインについての学習メモブログ

SVG入門 #8 SVGの色をCSSで変える — fillとstrokeでホバー時に色を変えよう

記事内に広告が含まれています。

SVG入門 #8 SVGの色をCSSで変える — fillとstrokeでホバー時に色を変えよう

SVGのアイコンを、マウスを重ねたときだけ別の色に変えたいと思ったことはありませんか。

ところが、CSSでcolorを指定してもアイコンの色が変わらなかったり、同じCSSを書いたのに効くSVGと効かないSVGがあったりして、つまずく人も多いはずです。

SVG入門シリーズの8回目、最終回です。

この記事では、SVGの色変更をCSSで行う方法を、fill(塗り)とstroke(線)の基本から、CSSで色を変えられる条件、ホバー時に色を変える書き方、currentColorで文字色と合わせる方法まで、初心者向けに解説します。

SVGそのものについては、SVGファイルとはで解説しています。

SVGの色の基本:fillとstroke

まずは、SVGの色を決める2つの指定「fill」と「stroke」の役割と、CSSで色を変えられる条件を押さえましょう。

fill(塗り)とstroke(線)とは

SVGの図形の色は、内側を塗る「fill」と、輪郭の線を描く「stroke」の2つで決まります。

SVGは、四角や円、線といった図形を「どこに・どんな形で描くか」を文字で書いた画像なので、色も図形ごとに「塗りは何色、線は何色」と指定する仕組みになっています。

線の太さはstroke-widthで指定します。

何も指定しないときは、fillは黒、strokeは「なし(none)」になるので、色を付けていない図形は黒く塗りつぶされ、輪郭線は描かれません(MDN「fill」、MDN「stroke」)。

下のコードは、同じ大きさの円を3つ並べて、塗りだけ・線だけ・塗りと線の両方を指定した例です。

<svg width="240" height="80" viewBox="0 0 240 80" role="img" aria-label="塗りと線の違いを示す3つの円" xmlns="http://www.w3.org/2000/svg">
  <circle cx="40" cy="40" r="30" fill="#FFBD07" />
  <circle cx="120" cy="40" r="30" fill="none" stroke="#7A5200" stroke-width="4" />
  <circle cx="200" cy="40" r="30" fill="#FFBD07" stroke="#7A5200" stroke-width="4" />
</svg>
上のコードを表示した結果。1つめは塗り(fill)だけ、2つめは線(stroke)だけ、3つめは塗りと線の両方

2つめの円のようにfill="none"にすると中が透明になり、線だけの図形になります。

#FFBD07のような色の書き方はHTMLやCSSと同じで、「#」から始まる6桁の数字と英字で色を表すカラーコードのほか、redのような色の名前も使えます(カラーコードの読み方はカラーコードとはで解説しています)。

色は属性でもCSSでも指定できる

fillとstrokeは、SVGのタグに書く「属性」(タグに付ける設定)としても、CSSの「プロパティ」(見た目を決める項目)としても指定できます。

上のコードのfill="#FFBD07"は属性での指定で、CSSで書く場合はfill: #FFBD07;のように、同じ名前のプロパティを使います(MDN「fill(CSSプロパティ)」)。

大事なのは、属性とCSSの両方で色が指定されていたら、CSSのほうが優先されるという決まりです。

MDNでも、fillやstrokeのような見た目のための属性(プレゼンテーション属性)は、同じ名前のCSSプロパティが指定されるとそちらが優先されると説明されています(MDN「fill」)。

つまり、SVGのコードに色が書き込まれていても、あとからCSSで上書きできるということで、これがCSSでSVGの色を変えられる理由です。

ただし、SVGの中でstyle="fill: …"のように、style属性(タグに直接書くCSS)で色が書かれている場合は別です。

style属性で書いたCSSは、スタイルシートの通常の指定より強いため、外から書いたCSSでは上書きできません(MDN「詳細度」)。

CSSで色を変えられるSVG・変えられないSVG

SVGの色をページのCSSで変えられるのは、SVGのコードをHTMLの中に直接書いた「インラインSVG」のときだけです。

<img src="icon.svg">のように画像として読み込んだSVGは、ページとは別の画像として扱われるため、ページのCSSが中の図形まで届きません。

MDNでも、img要素で読み込んだSVGは、CSSで中身を制御したい場合はSVGのコードの中にスタイルを書く必要があり、:focusのような擬似クラス(マウスを重ねた・選択したなどの状態を表すCSSの書き方)でスタイルを変えることもできない、と説明されています(MDN「HTML へのベクターグラフィックの追加」)。

CSSのbackground-image(背景画像)で読み込んだSVGにも、同じ制限があります。

一方、インラインSVGなら図形にclassを付けて、HTMLの要素と同じようにCSSで色を指定でき、マウスを重ねたときの変化も付けられます。

SVGの表示方法ページのCSSで色を変えるホバーで色を変える
インラインSVG(HTMLにコードを直接書く)できるできる
img要素で読み込むできないできない
CSSの背景画像(background-image)で読み込むできないできない

imgで読み込んだSVGの色を変えたいときは、色違いのSVGファイルを用意するか、インラインSVGに書き換えるのが入門では分かりやすい方法です。

CSSでSVGの色を変える方法

ここからは、インラインSVGの色をCSSで指定し、ホバー時に色を変え、文字色とそろえるまでを、実際に動く見本と一緒に進めます。

手順の全体像

SVGの色をCSSで変える流れは、次の4ステップです。

  1. SVGのコードを、imgで読み込まずにHTMLの中へ直接書く(インラインSVG)
  2. 色を変えたい図形(pathやcircleなど)にclassを付ける
  3. CSSで、そのクラスにfillやstrokeを指定する
  4. ホバー時の色を:hoverで指定する

SVGのコードは、テキストエディタでSVGファイルを開き、<svgから</svg>までをコピーしてHTMLに貼り付ければインラインSVGになります。

CSSでSVGの色を指定する

まずは、星形のアイコンにクラスを付けて、CSSで塗りと線の色を指定してみましょう。

下のコードは、path(線をつないで形を描く図形)にfill="#6B6256"(グレー)を属性で書いたうえで、CSSで黄色の塗りと茶色の線を指定する例です。

<style>
  .star-yellow {
    fill: #FFBD07;
    stroke: #7A5200;
  }
</style>

<svg width="64" height="64" viewBox="0 0 24 24" role="img" aria-label="星のアイコン" xmlns="http://www.w3.org/2000/svg">
  <path class="star-yellow" fill="#6B6256" d="M12 2 L15 9 L22 9.5 L16.5 14 L18.5 21 L12 17 L5.5 21 L7.5 14 L2 9.5 L9 9 Z" />
</svg>
見本A:クラスを付けない場合。fill属性のグレーで塗られる
見本B:上のコードを表示した結果。CSSの指定がfill属性より優先され、黄色の塗りと茶色の線になる

見本Bでは、pathにグレーのfill属性が書かれたままでも、CSSの色が優先されて黄色になっています。

CSSの#FFBD07を別のカラーコードに書き換えれば塗りの色が、#7A5200を書き換えれば線の色が変わります。

ホバー時にSVGの色を変える

マウスを重ねたときに色を変えるには、CSSの:hover(マウスを重ねている間だけ当てはまる指定)を使います(MDN「:hover」)。

下のコードは、ふだんは線だけのグレーの星で、星を囲む箱にマウスを重ねると黄色く塗られる例です。

<style>
  .star-box .star {
    fill: none;
    stroke: #6B6256;
    stroke-width: 1.5;
  }
  .star-box:hover .star {
    fill: #FFBD07;
    stroke: #7A5200;
  }
</style>

<div class="star-box">
  <svg width="64" height="64" viewBox="0 0 24 24" role="img" aria-label="星のアイコン" xmlns="http://www.w3.org/2000/svg">
    <path class="star" d="M12 2 L15 9 L22 9.5 L16.5 14 L18.5 21 L12 17 L5.5 21 L7.5 14 L2 9.5 L9 9 Z" />
  </svg>
</div>
上のコードを表示した結果。箱にマウスを重ねると星が黄色く塗られる(スマートフォンでは、タップしたときに変わる場合と変わらない場合がある)

ポイントは、:hoverを星の図形そのものではなく、外側の箱(.star-box)に付けていることです。

.star-box:hover .starは「箱にマウスが重なっているときの、箱の中の星」という意味なので、星の細い線の上を正確に狙わなくても、箱のどこに重ねても色が変わります。

実際のサイトでは、このdivの代わりにリンク(a要素)やボタン(button要素)にクラスを付けると、「押せるアイコン」のホバー表現になります。

ホバーで色を変える考え方そのものは、状態色とはで解説しています。

currentColorで文字色とSVGの色をそろえる

「続きを読む」の横の矢印のように、文字とアイコンを並べる場合は、currentColorを使うと文字色とSVGの色をまとめて管理できます。

currentColorは、その要素の文字色(colorプロパティ)の値をそのまま使うという意味のキーワードです(MDN「currentColor キーワード」)。

下のコードは、SVGの塗りをcurrentColorにして、ホバー時には文字色だけを変える例です。

<style>
  .more-link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: #7A5200;
  }
  .more-link:hover {
    color: #1F6FAE;
  }
  .more-link svg {
    fill: currentColor;
  }
</style>

<div class="more-link">
  続きを読む
  <svg width="16" height="16" viewBox="0 0 16 16" role="img" aria-label="右向きの矢印" xmlns="http://www.w3.org/2000/svg">
    <path d="M5 2 L11 8 L5 14 Z" />
  </svg>
</div>
上のコードを表示した結果。「続きを読む」にマウスを重ねると、文字と矢印が一緒に茶色から青に変わる

ホバー時のCSSではcolorしか変えていないのに、矢印の色も一緒に変わっています。

SVGのfillが「今の文字色」を指しているので、文字色が変われば矢印もそれに合わせて変わるからです。

色を変えたくなったときもcolorの値を1か所書き換えるだけで済むので、同じアイコンをいろいろな色のボタンやリンクで使い回すときに便利です。

線で描くアイコンの場合は、fillの代わりにstroke: currentColor;と書けば、線の色が文字色にそろいます(MDN「stroke(CSSプロパティ)」)。

実践のポイント

SVGの色をCSSで変えるときに陥りやすい失敗と、よくある疑問をまとめます。

注意点・よくある間違い

  • imgで読み込んだSVGに、ページのCSSで色を付けようとしてしまう。
    ページのCSSは画像として読み込んだSVGの中まで届かないので、色を変えたいSVGはインラインSVGにしましょう。
  • SVGの図形の色をcolorで変えようとしてしまう。
    図形の塗りはfill、線はstrokeで指定します。
    colorで変えたいときは、図形側にfill: currentColor;を書いておきましょう。
  • CSSを書いても色が変わらないのに、原因が分からない。
    SVGのコードを開いて、図形にstyle="fill: …"のようなstyle属性が書かれていないか確認しましょう。
    style属性の色は外のCSSより強いので、その部分を消すか、fill属性に書き直すとCSSが効くようになります。
  • 線だけで描かれたアイコンにfillで色を付け、中まで塗りつぶしてしまう。
    線のアイコンはstrokeのほうを変えましょう。
  • ホバーで色が変わることだけで、大事な情報を伝えてしまう。
    スマートフォンなどのタッチ画面ではホバーが働かないことがあるので、ホバーはあくまで補助の表現にとどめましょう(MDN「:hover」)。

よくある質問

  • Q. imgで読み込んだままSVGの色を変える方法はない?
    A. ページのCSSで中の図形の色を直接変えることはできません。
    応用的な方法もありますが、入門のうちは色違いのSVGファイルを用意するか、インラインSVGに書き換えるのが確実です。
  • Q. fillとcolorは何が違う?
    A. colorは文字の色、fillはSVGの図形の塗りの色を決めるプロパティです。
    2つは別物ですが、fill: currentColor;と書くと、SVGの塗りを文字色にそろえられます。
  • Q. ホバーで色をふわっと切り替えたい。
    A. CSSのtransitionを使うと、色を少しずつ変化させられます(MDNの「:hover」の例でも使われています)。
    動きを付ける表現はアニメーションの分野になるので、この入門シリーズでは扱いません。

まとめ

SVGの色は、内側を塗るfillと輪郭の線を描くstrokeで決まり、SVGのコードをHTMLに直接書いたインラインSVGなら、CSSで色を変えたりホバー時に色を変えたりできます。

imgや背景画像で読み込んだSVGにはページのCSSが届かないこと、文字とアイコンの色をそろえたいときはcurrentColorが便利なことも押さえておきましょう。

まずはこの記事のホバーのコードをHTMLファイルに貼り付けてブラウザで開き、#FFBD07を好きなカラーコードに変えて、マウスを重ねたときの色を確かめてみてください。

SVG入門シリーズのふりかえり

この記事で、SVG入門シリーズは終わりです。

全8回で学んできた内容を、最後にふりかえっておきましょう。

  1. SVGとは何か、PNG・JPGとの違いと向いている使い道
  2. SVGファイルをブラウザやテキストエディタで開き、中身が文字で書かれていることを確かめる
  3. Figma・Illustrator・Inkscapeなどのツールで描いて、SVGとして書き出す
  4. SVGをPNG・JPGに変換する
  5. PNG・JPGを画像トレースでSVGに変換する
  6. imgタグ・インラインSVG・CSS背景でWebページに表示する
  7. viewBoxと基本図形(rect・circle・path)でSVGのコードを読む
  8. fillとstrokeを使い、CSSでSVGの色を変える(この記事)

ここまで読めば、SVGを「開く・作る・変換する・Webに載せる・コードを読む・色を変える」という基本の操作はひと通りできるようになっています。

次のステップとしては、CSSでSVGに動きを付けるアニメーションや、書き出したSVGから不要な情報を取り除いてファイルを軽くする軽量化などがあり、どちらもこのシリーズで学んだコードの読み方とCSSの知識が土台になります。

まずは身の回りのWebサイトでアイコンにマウスを重ねてみて、色が変わるものを見つけたら、ブラウザの開発者ツール(ページのHTMLやCSSを調べられる、ブラウザに付いている機能)でfillやstrokeがどう書かれているかのぞいてみてください。