現場で役立つ、SVGアイコン調整術 第1回 SVGアイコンの色指定を攻略する

Webサイトやアプリケーションでアイコンを使用する際、SVG形式を選択することには多くのメリットがあります。本記事では、アイコンにSVGを使う理由と、HTML/CSSで直接カスタマイズできる柔軟性について解説します。

発行

著者 藤田 智朗 フロントエンド・エンジニア
現場で役立つ、SVGアイコン調整術 シリーズの記事一覧

はじめに

Webサイトやアプリケーションを構築する際、アイコンは欠かせない要素です。ナビゲーション、ボタン、ステータス表示など、あらゆる場面でアイコンが使われています。そんなアイコンの形式として、近年SVGが主流となってきました。

最近では、アイコンライブラリやデザインツールからSVGコードを直接扱う機会が増えてきました。商用でも利用できる優れたアイコンライブラリも存在しますが、プロジェクトによってはFigmaなどで作成された独自のアイコンを使用する必要があったり、ReactやVueでSVGアイコンをコンポーネント化して管理することも多くあります。

そのような場面で、色の調整、サイズの調整、線の調整、余白の制御など、実務で必要な微調整を素早く行わなければならないことがあります。本シリーズでは、そんなときに役立つSVGの知識やテクニックを解説します。

なお、このシリーズで紹介するデモは次のリポジトリにまとまっています。参考にしてください。

SVGの基礎シリーズとの違い

CodeGridでは、2014年の「マークアップ・エンジニアのためのSVG入門」シリーズでSVGの仕様や基本的な使い方を詳しく解説しました。このシリーズではSVGの全般的な機能(グラフィック、アニメーション、フィルターなど)を網羅的に扱っています(第8回と第9回の内容がブラウザの仕様変更の影響を受けていますが、多くの内容は現在でも通用する内容となっています)。

本シリーズは、SVGをアイコンとして使用することに特化した内容です。実務でよく直面する「アイコンの色を変えたい」「サイズを調整したい」「ダークモードに対応したい」といった具体的、かつ実用的な課題の解決方法に焦点を当てています。

SVGの基本的な仕組みを知りたい方は上記シリーズを、アイコンとしての実践的な活用方法を学びたい方は本シリーズをご覧ください。

SVGアイコンの特徴

SVGをアイコンとして使用する最大の魅力は、タグの属性やCSSで自由にスタイリングできることです。たとえば、次のようなことが比較的容易に制御可能です。画像やフォントのアイコンでは微調整が難しく、かなり手間が掛かってしまうものが少なくないでしょう。

  • 色の調整
  • サイズの調整
  • 線の調整(幅、角丸)
  • 余白の調整

具体的にどのように調節できるのか、次の節から詳しく解説します。

SVGのファイルサイズについての現実

ここで、SVGの特徴やメリットとしてよく言われる「ファイルサイズが小さい」という話が出ないな? と思った方もいるかもしれません。同じサイズの画像でもSVGなら「ファイルサイズが小さい」は常に正しいとは限りません。実際には、アイコンの複雑さによって大きく変わります。

SVGが有利な場合:

  • シンプルな幾何学図形(矢印、ハンバーガーメニュー、プラス記号など)
  • 直線や単純な曲線で構成されたデザイン

PNGの方がファイルサイズが小さくなる場合:

  • 複雑なイラスト調のアイコン
  • 細かいディテールが多いアイコン

筆者の経験ではパスが複雑なアイコンは、同じ幅・高さのPNGよりファイルサイズが大きくなることも珍しくありませんでした。そのため、本記事ではファイルサイズの軽量性をSVGの主要な特徴・メリットとしては挙げていません。

また、画像ファイル形式の選択指南 | 前編 PNG、JPEG、WebP 静止画像形式の選び方の記事内でもSVGとその他の画像形式との比較をしているので合わせてご確認ください。

色の調整

SVGの色は、塗りつぶし色のためのfillと描線色のためのstrokeで制御できます。

このfillstrokeの色指定は、fill属性やstroke属性による直接指定と、CSSによる指定(style属性またはclass属性経由)の両方が可能です。両方指定されている場合はCSSによる指定が優先されます。

アウトライン化されていない、つまりstrokeだけで表現されている図形の場合は注意が必要です。 fillが未指定の場合は初期値が適用されますが、fillの初期値は #000であるため、未指定の場合は図形の凹部分が塗りつぶされてしまいます。

凹部分が塗り潰されないようにするにはfill="none"としてfillnoneを明示します。

fillとstrokeの使用

<!-- rect(四角) -->
<!-- 塗りつぶし(fill) -->
<svg viewBox="0 0 24 24" fill="#007bff">
    <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
</svg>
<!-- 線(stroke) -->
<svg viewBox="0 0 24 24" stroke="#007bff" fill="none">
    <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
</svg>
<!-- fill属性とstyle属性のfillの両方を指定した場合 -->
<svg viewBox="0 0 24 24" fill="#007bff" style="fill: #dc3545;">
    <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
</svg>
<!-- stroke属性とstyle属性のstrokeの両方を指定した場合 -->
<svg viewBox="0 0 24 24" stroke="#007bff" style="stroke: #dc3545; fill: none;">
    <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
</svg>

<!-- path(>の形) -->
<!-- 線(stroke) -->
<svg viewBox="0 0 24 24" stroke="#007bff" fill="none">
    <path d="M9 5L15 12L9 19" />
</svg>

<!-- fillが未指定の場合 -->
<svg viewBox="0 0 24 24" stroke="#007bff">
    <path d="M9 5L15 12L9 19" />
</svg>

補足:viewBox属性

コード中にあるSVGのviewBox属性については、次回解説します。

fillstrokeを両方使用することも可能です。たとえば、塗りつぶしの色より濃い色を枠線に使うなど、より複雑な表現ができます。

fillとstrokeを両方使う

.combined-icon {
  fill: #007bff;
  stroke: #01458d;
}

currentColorの活用

currentColorは、その要素のテキスト色(colorプロパティ)を参照する便利な値です。

currentColorの活用

<style>
.primary-text {
  /* この色がテキストだけでなくアイコンにも適用される */
  color: #01458d;
}

.icon {
  width: 20px;
  height: 20px;
  vertical-align: middle;
  margin-right: 0.5em;
}
</style>

<div class="primary-text">
  <svg viewBox="0 0 24 24" class="icon">
    <!-- fill="currentColor"によってprimary-textのcolorの色が適用される -->
    <path fill="currentColor" d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
  </svg>
  <span>アクション</span>
</div>

この方法により、テキストとアイコンの色を一括で管理できます。

ダークモード対応

最近のOSやブラウザは、ユーザーの好みに応じてダークモードをサポートしています。SVGアイコンなら、メディアクエリを使ってダークモード時の色を簡単に切り替えることができます。画像ファイルのように別のアセットを用意する必要はありません。

カラーモードの切り替え

/* ライトモード */
.icon {
  stroke: #333;
}

/* ダークモード */
@media (prefers-color-scheme: dark) {
  /* ユーザーがダークテーマを設定している場合はこちらを適用 */
  .icon {
    stroke: #fff;
  }
}

サイズ調整

次はサイズに関する調整について解説します。SVGのサイズは、前述したfill属性、stroke属性と同様に、width属性とheight属性による直接指定と、CSSによる指定(style属性またはclass属性経由)の両方が可能です。これはimg要素と同じで、どちらもHTML仕様に従います。

サイズ調整

<!-- SVG属性での指定 -->
<svg viewBox="0 0 24 24" width="100" height="100">
  <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
</svg>

<!-- style属性での指定 -->
<svg viewBox="0 0 24 24" style="width: 100px; height: 100px;">
  <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
</svg>

CSSが指定されている場合はCSSが優先されます。

CSSが優先される

<!-- width/height属性とstyle属性を組み合わせた指定(style属性が優先される) -->
<svg viewBox="0 0 24 24" width="100" height="100" style="width: 200px; height: 200px;">
    <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
</svg>

次のデモでは、SVG属性とstyle属性の両方でスタイルを指定しています。

デモのソースコード

<html>

<head>
    <meta charset="UTF-8">
    <title>SVGアイコンのデモ</title>
</head>

<body>
    <div style="display: flex; align-items: center;">
        <!-- SVG属性での指定 -->
        <svg viewBox="0 0 24 24" width="100" height="100">
            <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
        </svg>

        <!-- style属性での指定 -->
        <svg viewBox="0 0 24 24" style="width: 100px; height: 100px;">
            <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
        </svg>

        <!-- SVG属性とstyle属性を組み合わせた指定(style属性が優先される) -->
        <svg viewBox="0 0 24 24" width="100" height="100" style="width: 200px; height: 200px;">
            <rect x="4" y="4" width="16" height="16" rx="4" ry="4" />
        </svg>
    </div>
</body>

</html>

実際のデモを見てみると、style属性が優先されていることが確認できます。

線の調整

SVGでは線の太さ、角丸も属性と値の指定によって細かく調整できます。順にどのように調整するのか確認しましょう。

線の太さ

strokeを使ったアイコンでは、stroke-widthで線の太さを調整できます。stroke-widthの値を大きくすると線が太くなります。

線の太さの調整

<style>
.stroke-thin path {
  fill: none;
  stroke: #000000;
  /* 線の太さに1を指定 */
  stroke-width: 1;
}

.stroke-bold path {
  fill: none;
  stroke: #000000;
  /* 線の太さに3を指定 */
  stroke-width: 3;
}
</style>

<svg viewBox="0 0 24 24" class="stroke-thin">
  <path d="M9 5L15 12L9 19"/>
</svg>

<!-- こちらの線が太くなる -->
<svg viewBox="0 0 24 24" class="stroke-bold">
  <path d="M9 5L15 12L9 19"/>
</svg>

stroke-widthを指定してもstrokeのカラー指定がないと線が表示されない点に注意してください。

SVGのpath要素について

ここで上記で使用しているpath要素のd属性について簡単に説明しておきます。dは"data"の略で、パスの形状を定義する命令の連続です。次回解説するviewBoxにも関係しますので、覚えておいてください。

SVGの座標系は、左上が原点(0, 0)で、右方向がX軸の正の方向、下方向がY軸の正の方向となります。これはCSSやCanvasと同じ座標系です。

d属性(右向きの矢印)

d="M9 5L15 12L9 19"

この例は右向きの矢印(>)を描いています:

  • M9 5: ペンを座標(9, 5)に移動(Move to)- 原点から右に9、下に5の位置
  • L15 12: 座標(15, 12)まで直線を引く(Line to)- 原点から右に15、下に12の位置
  • L9 19: 座標(9, 19)まで直線を引く - 原点から右に9、下に19の位置

結果として、3つの点を結んだV字型(>)のパスが描かれます。これは線描の典型例です。strokeで表し、前述したようにfillnoneにしておく必要があります。

線の角丸処理

strokeを使ったアイコンでは、stroke-linecapstroke-linejoin属性を使って線の端や接続部分を丸くできます。柔らかく親しみやすい印象のアイコンにしたい場合に利用すると良いでしょう。 これは、アウトライン化せずに線のまま表現する際の利点です。

stroke-linecapは線の端の形状を制御し、stroke-linejoinは線の接続部分(角の部分)の形状を制御します。角丸を作るには、それぞれroundを指定します。

形状の指定

stroke-linecapstroke-linejoinには、round以外にも指定できる値があります。興味のある方は次のリンクなどを参照してください。

角丸処理

<style>
.stroke {
  fill: none;
  stroke: #000000;
  stroke-width: 3;
}

.stroke-round {
  fill: none;
  stroke: #000000;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
</style>

まとめ

今回はSVGアイコンにおける色、サイズ、線の微調整といった基本的なことについて解説しました。 冒頭でも述べたように例えばコンポーネント化したうえでプロパティで微調整できるようにしたいケースでこれらの知識があると役立つことがあるかと思います。

次回はviewBoxとそれを使った余白の調整方法について解説します。