SVGコードの書き方完全ガイド|基本構造・pathコマンド・最適化・表示トラブルまで解説

svg-code-guide その他
記事内に広告が含まれています。

Webサイトやアプリのデザインで欠かせない存在となった「SVG」。

拡大しても劣化せず、コードで自在にカスタマイズできるこのフォーマットは、アイコンやロゴ、アニメーションなどに幅広く使われています。

しかし、いざ「SVGコードを書こう」と思っても、「どのタグを使えばいいの?」「viewBoxって何?」「Illustratorで書き出したコードが長すぎる…」といった疑問を抱える方は多いのではないでしょうか。

特に、HTML内に直接SVGを書く方法や、<path>タグの座標指定の仕組み、fillstrokeによる色の設定方法などは、初心者にとって理解しづらいポイントです。

また、Web制作の現場では「デザインツールから出力されたSVGを最適化して軽くしたい」「レスポンシブ対応にしたい」といった実践的な課題にも直面します。

この記事では、「SVGコードの仕組み」から「実践的な書き方」「最適化・トラブル対策」までを、具体的なコード例とともにわかりやすく解説します。

単に構文を学ぶだけでなく、「実務で活かせるSVGスキル」を身につけられる内容です。

この記事を読んでわかること

  • SVGがベクター形式である理由と、PNGやJPGとの根本的な違い
  • <svg><circle><rect>など基本タグの使い方と属性の意味
  • <path>タグのM・L・Cコマンドによる図形描画の仕組み
  • viewBoxwidth/heightを活用したレスポンシブ対応の方法
  • fillstrokeによる色や線の制御と、CSSとの連携方法
  • SVGコードを軽量化するためのツール(SVGOMG・SVGO)の使い方
  • Illustratorで最適なSVGを書き出すための設定ポイント
  • SVGをbase64形式でHTMLやCSSに埋め込む方法
  • SVGが正しく表示されないときの原因と解決策
  • SEOやアクセシビリティを考慮した安全なSVGの使い方

これからSVGを使いこなしたいWeb制作者やデザイナーにとって、この記事は「SVGをコードから理解する」ための最短ルートになるはずです。

◆◇◆ 【衝撃価格】VPS512MBプラン!1時間1.3円【ConoHa】 ◆◇◆

SVGコードとは?仕組みと基本構造をわかりやすく解説

SVG(Scalable Vector Graphics)は、Web制作において欠かせない画像形式の一つです。このセクションでは、SVGの本質的な仕組みと、コードを書く上で理解すべき基本構造について、技術的な背景を含めて詳しく解説します。

SVGがベクター形式である理由と画像形式(PNG・JPG)との違い

SVGがベクター形式である最大の理由は、画像を数式(座標と図形の定義)で表現するという根本的なアプローチにあります。これに対して、PNGやJPGなどのラスター形式は、画像をピクセルの集合体として表現します。

ベクターとラスターの技術的な違い

ラスター形式(PNG・JPG)は、画像を固定されたグリッド上のピクセル(画素)の集合として保存します。例えば、100×100pxの画像であれば、10,000個のピクセルそれぞれに色情報を持たせます。この方式の問題点は、拡大時に元々存在しないピクセル情報を補間する必要があり、その結果ボケやギザギザ(ジャギー)が発生することです。

ベクター形式(SVG)は、「座標(50, 50)を中心に半径30の円を描く」といった数学的な指示として画像を定義します。表示時には、その指示に従ってブラウザが計算し、現在の表示サイズに最適な形でレンダリングします。そのため、どのサイズで表示しても常に鮮明な状態を保てるのです。

SVGの具体的なメリット

  • 拡大しても劣化しない:
    4Kディスプレイでも、スマートフォンの小さな画面でも、常に最適な品質で表示されます
  • ファイルサイズが軽い:
    複雑でない図形であれば、ラスター画像よりも大幅に軽量です(シンプルなアイコンで数KB以下)
  • CSSやJavaScriptで動的に操作可能:
    色の変更、アニメーション、インタラクティブな挙動を柔軟に実装できます
  • 検索エンジンがテキストとして認識:
    SVG内のテキストは通常のHTMLテキストと同様にインデックスされます

XMLベースの構造がもたらす利点

SVGはXML(Extensible Markup Language)ベースのマークアップ言語です。これは、HTMLと同じ文法規則に従っており、開発者にとって以下のメリットがあります。

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db" />
</svg>

XMLであることのメリット

  • テキストエディタで直接編集可能:
    画像編集ソフトがなくても、コードで精密な調整ができます
  • バージョン管理システムとの親和性:
    Gitなどで差分管理ができ、チーム開発に適しています
  • DOM操作が可能:
    JavaScriptで要素を追加・削除・変更できます

SVGコードの基本構造<svg>とviewBoxのルール

SVGコードを正しく書くためには、<svg>タグの構造と、特に重要なviewBox属性の仕組みを理解する必要があります。

<svg>タグの必須属性と推奨属性

最小限のSVGコードは以下のような構造になります。

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 200 200" width="200" height="200">
  <!-- ここに図形要素を配置 -->
</svg>

主要な属性の解説:

  • xmlns="<http://www.w3.org/2000/svg>":
    XML名前空間の宣言。HTML内にインラインで記述する場合は省略可能ですが、SVGファイルとして独立させる場合は必須です。この宣言により、ブラウザは「これはSVG要素である」と認識します。
  • viewBox="min-x min-y width height":
    SVG内部の座標系を定義します。これがSVGの核心となる概念です。
  • widthheight:
    実際の表示サイズを指定します。単位を省略するとピクセル(px)として扱われます。

viewBoxが座標系とキャンバスサイズを定義する仕組み

viewBoxは、SVGの内部座標系を定義する最も重要な属性です。4つの数値で構成されます。

viewBox="min-x min-y width height"

各パラメータの意味:

  • min-x: 表示領域の左上のX座標(通常は0)
  • min-y: 表示領域の左上のY座標(通常は0)
  • width: 内部座標系の幅
  • height: 内部座標系の高さ

具体例で理解するviewBoxの動作

例1: 基本的な使い方

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100" width="200" height="200">
  <circle cx="50" cy="50" r="40" fill="#e74c3c" />
</svg>

この例では:

  • viewBox="0 0 100 100": 内部座標系は100×100の領域
  • width="200" height="200": 実際の表示は200×200px
  • 円の中心cx="50" cy="50"は、内部座標系の中心に配置されます
  • 結果として、円は2倍に拡大されて表示されます(viewBoxが100で実サイズが200のため)

例2: トリミング効果

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="50 50 50 50" width="200" height="200">
  <circle cx="75" cy="75" r="40" fill="#2ecc71" />
</svg>

この例では:

  • viewBox="50 50 50 50": 座標(50,50)を起点に、50×50の領域だけを表示
  • 円の右下1/4の部分だけが切り取られて、200×200pxに拡大表示されます

なぜこの仕組みが重要か:

viewBoxを理解することで、以下が可能になります。

  • レスポンシブデザイン:
    widthheightを%で指定し、viewBoxで内部比率を保つことで、親要素に応じて自動的にスケーリングされます
  • アートボードの管理:
    デザインツールで作成した座標系をそのまま維持できます
  • ズームやパン効果:
    JavaScriptでviewBoxの値を動的に変更することで、SVGのズームイン/アウトが実装できます

基本図形(<circle>・<rect>・<polygon>)の書き方と属性チートシート

SVGには、複雑な<path>を使わなくても描ける基本図形要素が用意されています。これらをマスターすることで、多くのグラフィックスを効率的に作成できます。

<circle> – 円

基本構文:

<circle cx="50" cy="50" r="30" fill="#9b59b6" stroke="#8e44ad" stroke-width="2" />

属性一覧:

属性必須説明
cx円の中心のX座標cx="50"
cy円の中心のY座標cy="50"
r半径r="30"
fill×塗りつぶしの色fill="#9b59b6"
stroke×輪郭線の色stroke="#8e44ad"
stroke-width×輪郭線の太さstroke-width="2"

<rect> – 矩形

基本構文:

<rect x="10" y="10" width="80" height="50" rx="5" ry="5" fill="#3498db" />

属性一覧:

属性必須説明
x矩形の左上のX座標x="10"
y矩形の左上のY座標y="10"
widthwidth="80"
height高さheight="50"
rx×X軸方向の角丸の半径rx="5"
ry×Y軸方向の角丸の半径ry="5"
fill×塗りつぶしの色fill="#3498db"

角丸のポイント: rxだけを指定した場合、ryrxと同じ値として扱われます。楕円形の角丸を作りたい場合は、両方を個別に指定します。

<ellipse> – 楕円

基本構文:

<ellipse cx="100" cy="50" rx="80" ry="30" fill="#e67e22" />

属性一覧:

属性必須説明
cx楕円の中心のX座標cx="100"
cy楕円の中心のY座標cy="50"
rxX軸方向の半径rx="80"
ryY軸方向の半径ry="30"

<line> – 直線

基本構文:

<line x1="10" y1="10" x2="90" y2="90" stroke="#e74c3c" stroke-width="3" />

属性一覧:

属性必須説明
x1始点のX座標x1="10"
y1始点のY座標y1="10"
x2終点のX座標x2="90"
y2終点のY座標y2="90"
stroke×線の色stroke="#e74c3c"
stroke-width×線の太さstroke-width="3"

注意: <line>にはfill属性は適用されません(線なので塗りつぶしの概念がない)。

<polyline> – 折れ線

基本構文:

<polyline points="10,10 50,50 90,10 130,50" fill="none" stroke="#1abc9c" stroke-width="2" />

属性:

points: 座標の連続をスペースまたはカンマ区切りで指定します。各座標はx,yの形式です。

<polygon> – 多角形

基本構文:

<polygon points="50,10 90,90 10,90" fill="#f39c12" stroke="#e67e22" stroke-width="2" />

属性:

points: <polyline>と同じ形式ですが、自動的に最後の点と最初の点が結ばれて閉じた図形になります。

実践例: 基本図形を組み合わせたアイコン

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100" width="100" height="100">
  <!-- 家のアイコン -->
  <polygon points="50,20 90,50 80,50 80,80 60,80 60,60 40,60 40,80 20,80 20,50 10,50" fill="#e74c3c" stroke="#c0392b" stroke-width="2"/>
  <rect x="43" y="50" width="14" height="10" fill="#34495e" />
</svg>

基本図形を使うメリット

  • 可読性が高い: <path>に比べて、コードの意図が明確に伝わります
  • メンテナンスしやすい: 属性値を変更するだけで図形を調整できます
  • パフォーマンス: ブラウザの最適化により、基本図形のレンダリングは高速です

基本図形をマスターすることで、SVGコードの書き方の基礎が固まり、より複雑な<path>要素への理解もスムーズになります。次のセクションでは、<path>を使った複雑な図形の描画とレスポンシブ対応について詳しく解説します。

格安ドメイン取得サービス─ムームードメイン─

SVGコードの核心:複雑な図形とレスポンシブ対応をマスターする

基本図形をマスターしたら、次はSVGの真髄である<path>要素と、あらゆるデバイスに対応するレスポンシブ設計を習得しましょう。このセクションでは、プロフェッショナルなWeb制作に不可欠な技術を詳しく解説します。

パス(<path>)の書き方とM/L/Cコマンドの意味を徹底解説

<path>要素は、SVGにおいて最も強力で柔軟な図形描画ツールです。直線、曲線、複雑な形状まで、あらゆる図形をd属性の中に記述されたパスコマンドで表現できます。

<path>の基本構造

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 200 200" width="200" height="200">
  <path d="M 10 10 L 50 50 L 10 90 Z" fill="#3498db" stroke="#2980b9" stroke-width="2" />
</svg>

すべてのパス情報はd(data)属性に記述されます。この属性には、複数のコマンドを空白またはカンマで区切って記述します。

主要なパスコマンド一覧

パスコマンドは大文字と小文字で動作が異なります。

  • 大文字: 絶対座標(SVG座標系の原点からの座標)
  • 小文字: 相対座標(現在位置からの相対的な移動)

M (Move to) – ペンの移動

構文: M x y または m dx dy

描画を開始する位置にペンを移動します。線は引かれません。パスは通常Mコマンドから始まります。

<!-- 絶対座標: 座標(50, 50)に移動 -->
<path d="M 50 50 L 100 100" stroke="#000" />

<!-- 相対座標: 現在位置から右に50、下に50移動 -->
<path d="M 10 10 m 40 40 L 100 100" stroke="#000" />

L (Line to) – 直線

構文: L x y または l dx dy

現在位置から指定した座標まで直線を引きます。

<svg viewBox="0 0 200 100">
  <!-- 絶対座標で三角形を描く -->
  <path d="M 10 80 L 50 10 L 90 80 Z" fill="none" stroke="#e74c3c" stroke-width="2"/>
</svg>

相対座標の例:

<svg viewBox="0 0 200 100">
  <!-- 階段状の図形 -->
  <path d="M 10 90 l 20 0 l 0 -20 l 20 0 l 0 -20 l 20 0 l 0 -20"
        fill="none" stroke="#3498db" stroke-width="2"/>
</svg>

この例では:

  • M 10 90: 座標(10, 90)からスタート
  • l 20 0: 現在位置から右に20移動(水平線)
  • l 0 -20: 現在位置から上に20移動(垂直線)
  • これを繰り返して階段を描画

実際の表示

See the Pen svg-code-guide-01 by watashi-xyz (@watashi-xyz) on CodePen.

H (Horizontal) と V (Vertical) – 水平線・垂直線

構文: H x / h dx (水平線), V y / v dy (垂直線)

一方向のみの移動を簡潔に記述できます。

<svg viewBox="0 0 200 100">
  <!-- 格子模様 -->
  <path d="M 10 10 H 190 M 10 30 H 190 M 10 50 H 190"
        stroke="#95a5a6" stroke-width="1"/>
  <path d="M 10 10 V 90 M 50 10 V 90 M 90 10 V 90"
        stroke="#95a5a6" stroke-width="1"/>
</svg>

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

C (Cubic Bézier Curve) – 3次ベジェ曲線

構文: C x1 y1, x2 y2, x y または c dx1 dy1, dx2 dy2, dx dy

2つの制御点を使った滑らかな曲線を描きます。これがSVGで最も頻繁に使用される曲線コマンドです。

パラメータの意味:

  • (x1, y1): 第1制御点(始点側の曲線の方向を決める)
  • (x2, y2): 第2制御点(終点側の曲線の方向を決める)
  • (x, y): 終点座標
<svg viewBox="0 0 200 100">
  <!-- S字カーブ -->
  <path d="M 10 50 C 40 10, 60 10, 90 50 C 120 90, 140 90, 170 50"
        fill="none" stroke="#9b59b6" stroke-width="3"/>

  <!-- 制御点を可視化(開発時のデバッグ用) -->
  <circle cx="40" cy="10" r="2" fill="red"/>
  <circle cx="60" cy="10" r="2" fill="red"/>
  <line x1="10" y1="50" x2="40" y2="10" stroke="red" stroke-width="1" opacity="0.5"/>
  <line x1="90" y1="50" x2="60" y2="10" stroke="red" stroke-width="1" opacity="0.5"/>
</svg>

実際の表示

See the Pen svg-code-guide-03 by watashi-xyz (@watashi-xyz) on CodePen.

S (Smooth Cubic Bézier) – 滑らかな3次ベジェ曲線

構文: S x2 y2, x y または s dx2 dy2, dx dy

前のCコマンドの第2制御点を基準に、自動的に第1制御点を計算して滑らかな曲線を描きます。連続した波形を描く際に便利です。

<svg viewBox="0 0 200 100">
  <!-- 波形 -->
  <path d="M 10 50 C 30 20, 50 20, 70 50 S 110 80, 130 50 S 170 20, 190 50"
        fill="none" stroke="#1abc9c" stroke-width="3"/>
</svg>

実際の表示

See the Pen svg-code-guide-04 by watashi-xyz (@watashi-xyz) on CodePen.

Q (Quadratic Bézier Curve) – 2次ベジェ曲線

構文: Q x1 y1, x y または q dx1 dy1, dx dy

1つの制御点で曲線を描きます。Cコマンドよりシンプルですが、制御の自由度は低くなります。

<svg viewBox="0 0 200 100">
  <!-- 放物線 -->
  <path d="M 10 90 Q 100 10, 190 90"
        fill="none" stroke="#f39c12" stroke-width="3"/>

  <!-- 制御点を可視化 -->
  <circle cx="100" cy="10" r="3" fill="red"/>
</svg>

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

A (Arc) – 円弧

構文: A rx ry x-axis-rotation large-arc-flag sweep-flag x y

楕円の一部を描きます。SVGで最も複雑なコマンドですが、円形のUIパーツ(プログレスバーなど)に不可欠です。

パラメータ:

  • rx, ry: 楕円のX軸・Y軸の半径
  • x-axis-rotation: 楕円の回転角度(度数法)
  • large-arc-flag: 0=小さい弧、1=大きい弧
  • sweep-flag: 0=反時計回り、1=時計回り
  • x, y: 終点座標
<svg viewBox="0 0 200 200">
  <!-- 75%のプログレスリング -->
  <path d="M 100 20 A 80 80 0 1 1 20 100"
        fill="none" stroke="#2ecc71" stroke-width="10" stroke-linecap="round"/>
</svg>

実際の表示

See the Pen svg-code-guide-06 by watashi-xyz (@watashi-xyz) on CodePen.

Z (Close Path) – パスを閉じる

構文: Z または z (大文字・小文字の区別なし)

現在位置から開始点まで直線を引いてパスを閉じます。

<svg viewBox="0 0 100 100">
  <!-- 三角形(Zで自動的に閉じる) -->
  <path d="M 50 10 L 90 90 L 10 90 Z" fill="#e74c3c"/>
</svg>

実践例: ハートマークを描く

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100" width="100" height="100">
  <path d="M 50 80
           C 40 70, 30 60, 30 50
           C 30 40, 35 30, 45 30
           C 50 30, 50 35, 50 40
           C 50 35, 50 30, 55 30
           C 65 30, 70 40, 70 50
           C 70 60, 60 70, 50 80 Z"
        fill="#e74c3c"/>
</svg>

実際の表示

See the Pen svg-code-guide-07 by watashi-xyz (@watashi-xyz) on CodePen.

パスコマンドを読み解くコツ

  1. まずMコマンドを探す:
    パスの開始点を特定します
  2. 大文字・小文字に注意:
    座標系が絶対か相対かを判断します
  3. 数値のペアを数える:
    Cなら6個(制御点2つ+終点)、Lなら2個(終点)と覚えておくと理解しやすくなります
  4. 制御点を可視化:
    開発中は制御点を<circle>で表示すると、曲線の構造が理解できます
月額99円から。容量最大1TB!ブログ作成におすすめのWordPressテーマ「Cocoon」も簡単インストール

viewBoxとwidth/heightでレスポンシブ対応を実現する方法

SVGをレスポンシブに表示することは、現代のWeb制作において必須のスキルです。viewBoxwidth/heightの適切な組み合わせで、あらゆるデバイスに最適化されたグラフィックスを実現できます。

レスポンシブSVGの基本パターン

パターン1: 親要素の幅に合わせて自動スケーリング

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 200 100" width="100%" height="auto">
  <rect x="10" y="10" width="180" height="80" fill="#3498db" rx="10"/>
</svg>

この設定により:

  • viewBox="0 0 200 100": 内部座標系は200×100(アスペクト比2:1)
  • width="100%": 親要素の幅いっぱいに表示
  • height="auto": アスペクト比を保って高さが自動調整される

重要: height="auto"を指定することで、viewBoxで定義したアスペクト比が維持されます。

viewBoxと実サイズの関係

<!-- ケース1: viewBoxと実サイズが同じ → 等倍表示 -->
<svg viewBox="0 0 100 100" width="100" height="100">
  <circle cx="50" cy="50" r="40" fill="#e74c3c"/>
</svg>

<!-- ケース2: 実サイズがviewBoxの2倍 → 2倍に拡大 -->
<svg viewBox="0 0 100 100" width="200" height="200">
  <circle cx="50" cy="50" r="40" fill="#2ecc71"/>
</svg>

<!-- ケース3: viewBoxが実サイズの2倍 → 1/2に縮小 -->
<svg viewBox="0 0 200 200" width="100" height="100">
  <circle cx="100" cy="100" r="80" fill="#9b59b6"/>
</svg>

スケーリング係数の計算式:

スケール = 実サイズ / viewBoxのサイズ

CSSでレスポンシブ対応を実装する

方法1: max-widthで最大サイズを制限

<style>
  .responsive-svg {
    width: 100%;
    height: auto;
    max-width: 500px; /* 最大サイズを制限 */
    display: block;
  }
</style>

<svg class="responsive-svg" viewBox="0 0 200 100" xmlns="<http://www.w3.org/2000/svg>">
  <rect width="200" height="100" fill="#1abc9c"/>
</svg>

方法2: aspect-ratioで比率を明示(モダンブラウザ)

<style>
  .aspect-svg {
    width: 100%;
    aspect-ratio: 16 / 9;
  }
</style>

<svg class="aspect-svg" viewBox="0 0 1600 900" xmlns="<http://www.w3.org/2000/svg>">
  <rect width="1600" height="900" fill="#f39c12"/>
</svg>

コンテナを使ったレスポンシブテクニック

パディングハックを使った古典的手法(IE11対応が必要な場合)

<style>
  .svg-container {
    position: relative;
    width: 100%;
    padding-bottom: 50%; /* 高さ=幅の50%(2:1の比率) */
    height: 0;
    overflow: hidden;
  }

  .svg-container svg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
</style>

<div class="svg-container">
  <svg viewBox="0 0 200 100" xmlns="<http://www.w3.org/2000/svg>">
    <rect width="200" height="100" fill="#e67e22"/>
  </svg>
</div>

preserveAspectRatio属性の役割と設定値

preserveAspectRatio属性は、viewBoxと実際の表示領域のアスペクト比が異なる場合に、SVGをどのように配置・スケーリングするかを制御します。

基本構文

preserveAspectRatio="<align> <meetOrSlice>"

align(配置)の値

形式: x{Min|Mid|Max}Y{Min|Mid|Max}

  • xMin: 左寄せ
  • xMid: 中央揃え(水平)
  • xMax: 右寄せ
  • YMin: 上寄せ
  • YMid: 中央揃え(垂直)
  • YMax: 下寄せ

よく使う組み合わせ:

<!-- 中央配置(デフォルト) -->
<svg viewBox="0 0 100 100" width="200" height="100" preserveAspectRatio="xMidYMid meet">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

<!-- 左上に配置 -->
<svg viewBox="0 0 100 100" width="200" height="100" preserveAspectRatio="xMinYMin meet">
  <circle cx="50" cy="50" r="40" fill="#e74c3c"/>
</svg>

<!-- 右下に配置 -->
<svg viewBox="0 0 100 100" width="200" height="100" preserveAspectRatio="xMaxYMax meet">
  <circle cx="50" cy="50" r="40" fill="#2ecc71"/>
</svg>

meetOrSlice(スケーリング方法)

meet(デフォルト): アスペクト比を保ち、全体が表示領域に収まるようにスケーリング(object-fit: containに相当)

<svg viewBox="0 0 100 50" width="200" height="200" preserveAspectRatio="xMidYMid meet">
  <rect width="100" height="50" fill="#9b59b6"/>
</svg>
<!-- 結果: 200×100の矩形として中央配置され、上下に余白ができる -->

slice: アスペクト比を保ち、表示領域を完全に埋めるようにスケーリング。はみ出た部分は切り取られます(object-fit: coverに相当)

<svg viewBox="0 0 100 50" width="200" height="200" preserveAspectRatio="xMidYMid slice">
  <rect width="100" height="50" fill="#1abc9c"/>
</svg>
<!-- 結果: 400×200にスケールされ、上下がトリミングされる -->

none: アスペクト比を無視して、表示領域に合わせて伸縮

<svg viewBox="0 0 100 100" width="200" height="100" preserveAspectRatio="none">
  <circle cx="50" cy="50" r="40" fill="#f39c12"/>
</svg>
<!-- 結果: 円が楕円に変形する -->

実践例: 背景画像として使う

<style>
  .hero-background {
    width: 100%;
    height: 400px;
  }
</style>

<svg class="hero-background" viewBox="0 0 1920 1080" preserveAspectRatio="xMidYMid slice">
  <defs>
    <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:#667eea;stop-opacity:1" />
      <stop offset="100%" style="stop-color:#764ba2;stop-opacity:1" />
    </linearGradient>
  </defs>
  <rect width="1920" height="1080" fill="url(#grad)"/>
</svg>

この設定により、画面幅に関わらず背景が常に画面いっぱいに表示されます。

色・線を自在に操る:fill属性とstroke属性によるスタイル指定の基本

SVGのスタイリングは、HTML要素と同様に複数の方法で指定できます。それぞれの特徴を理解し、状況に応じて最適な方法を選択しましょう。

スタイル指定の3つの方法

方法1: インライン属性(プレゼンテーション属性)

<svg viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db" stroke="#2980b9" stroke-width="3"/>
</svg>

メリット:

  • 最もシンプルで直感的
  • 要素ごとに個別のスタイルを簡単に指定できる

デメリット:

  • 大量の要素がある場合、コードが冗長になる
  • 一括変更が困難

方法2: <style>タグ内でのCSS定義

<svg viewBox="0 0 200 100" xmlns="<http://www.w3.org/2000/svg>">
  <style>
    .primary-shape {
      fill: #e74c3c;
      stroke: #c0392b;
      stroke-width: 2;
    }
    .primary-shape:hover {
      fill: #c0392b;
    }
  </style>
  <circle class="primary-shape" cx="50" cy="50" r="40"/>
  <rect class="primary-shape" x="120" y="10" width="70" height="80"/>
</svg>

メリット:

  • 複数の要素に同じスタイルを適用できる
  • :hoverなどの疑似クラスが使える
  • SVG内で完結するため、ファイルとして独立性が高い

デメリット:

  • SVGファイルサイズがやや増加する

方法3: 外部CSSファイルでの定義

<!-- HTML -->
<svg class="icon" viewBox="0 0 100 100">
  <circle class="icon-circle" cx="50" cy="50" r="40"/>
</svg>
/* 外部CSS */
.icon-circle {
  fill: #9b59b6;
  stroke: #8e44ad;
  stroke-width: 3;
  transition: fill 0.3s ease;
}

.icon:hover .icon-circle {
  fill: #8e44ad;
}

メリット:

  • サイト全体でスタイルを統一管理できる
  • CSS の cascade と specificity を活用できる
  • アニメーションやトランジションを柔軟に制御

デメリット:

  • 外部ファイル(<img>タグやbackground-image)として読み込んだSVGには適用されない

fill属性の詳細

基本的な色指定:

<!-- カラーネームで指定 -->
<circle cx="50" cy="50" r="40" fill="red"/>

<!-- 16進数カラーコード -->
<circle cx="50" cy="50" r="40" fill="#3498db"/>

<!-- RGB/RGBA -->
<circle cx="50" cy="50" r="40" fill="rgb(52, 152, 219)"/>
<circle cx="50" cy="50" r="40" fill="rgba(52, 152, 219, 0.5)"/>

<!-- HSL/HSLA -->
<circle cx="50" cy="50" r="40" fill="hsl(204, 70%, 53%)"/>

<!-- 塗りつぶしなし -->
<circle cx="50" cy="50" r="40" fill="none" stroke="#000"/>

グラデーション:

<svg viewBox="0 0 200 100">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:#e74c3c;stop-opacity:1" />
      <stop offset="100%" style="stop-color:#f39c12;stop-opacity:1" />
    </linearGradient>
  </defs>
  <rect width="200" height="100" fill="url(#grad1)"/>
</svg>

実際の表示

See the Pen svg-code-guide-08 by watashi-xyz (@watashi-xyz) on CodePen.

パターン:

<svg viewBox="0 0 200 200">
  <defs>
    <pattern id="dots" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
      <circle cx="10" cy="10" r="3" fill="#3498db"/>
    </pattern>
  </defs>
  <rect width="200" height="200" fill="url(#dots)"/>
</svg>

実際の表示

See the Pen svg-code-guide-09 by watashi-xyz (@watashi-xyz) on CodePen.

stroke属性の発展的な使い方

基本的なstroke属性:

<line x1="10" y1="50" x2="190" y2="50"
      stroke="#e74c3c"
      stroke-width="5"/>

stroke-linecap – 線端の形状:

<svg viewBox="0 0 200 120">
  <!-- butt (デフォルト): 線端が平ら -->
  <line x1="20" y1="30" x2="180" y2="30" stroke="#000" stroke-width="20" stroke-linecap="butt"/>
  <text x="20" y="20" font-size="12">butt</text>

  <!-- round: 線端が丸い -->
  <line x1="20" y1="60" x2="180" y2="60" stroke="#000" stroke-width="20" stroke-linecap="round"/>
  <text x="20" y="50" font-size="12">round</text>

  <!-- square: 線端が四角く突き出る -->
  <line x1="20" y1="90" x2="180" y2="90" stroke="#000" stroke-width="20" stroke-linecap="square"/>
  <text x="20" y="80" font-size="12">square</text>
</svg>

実際の表示

See the Pen svg-code-guide-10 by watashi-xyz (@watashi-xyz) on CodePen.

stroke-linejoin – 線の接合部の形状:

<svg viewBox="0 0 300 120">
  <!-- miter (デフォルト): 鋭角 -->
  <polyline points="20,30 60,70 100,30" fill="none" stroke="#000" stroke-width="15" stroke-linejoin="miter"/>

  <!-- round: 丸い接合 -->
  <polyline points="120,30 160,70 200,30" fill="none" stroke="#000" stroke-width="15" stroke-linejoin="round"/>

  <!-- bevel: 面取り -->
  <polyline points="220,30 260,70 300,30" fill="none" stroke="#000" stroke-width="15" stroke-linejoin="bevel"/>
</svg>

実際の表示

See the Pen svg-code-guide-11 by watashi-xyz (@watashi-xyz) on CodePen.

stroke-dasharray – 破線パターン:

<svg viewBox="0 0 200 150">
  <!-- 実線 -->
  <line x1="10" y1="20" x2="190" y2="20" stroke="#000" stroke-width="2"/>

  <!-- 均等な破線 -->
  <line x1="10" y1="40" x2="190" y2="40" stroke="#000" stroke-width="2" stroke-dasharray="5,5"/>

  <!-- 長短の破線 -->
  <line x1="10" y1="60" x2="190" y2="60" stroke="#000" stroke-width="2" stroke-dasharray="10,5"/>

  <!-- 複雑なパターン -->
  <line x1="10" y1="80" x2="190" y2="80" stroke="#000" stroke-width="2" stroke-dasharray="15,5,5,5"/>

  <!-- 一点鎖線 -->
  <line x1="10" y1="100" x2="190" y2="100" stroke="#000" stroke-width="2" stroke-dasharray="20,5,5,5"/>
</svg>

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

stroke-dasharrayの値は「線の長さ, 空白の長さ」の繰り返しパターンを定義します。

stroke-dashoffset – 破線の開始位置をずらす:

<svg viewBox="0 0 200 100">
  <style>
    .animated-dash {
      stroke-dasharray: 300;
      stroke-dashoffset: 300;
      animation: dash 2s linear forwards;
    }
    @keyframes dash {
      to {
        stroke-dashoffset: 0;
      }
    }
  </style>
  <circle class="animated-dash" cx="100" cy="50" r="40"
          fill="none" stroke="#3498db" stroke-width="3"/>
</svg>

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

このテクニックは、SVG描画アニメーションで頻繁に使用されます。

stroke-opacity – 線の透明度:

<svg viewBox="0 0 200 100">
  <line x1="50" y1="10" x2="50" y2="90" stroke="#e74c3c" stroke-width="40" stroke-opacity="0.3"/>
  <line x1="100" y1="10" x2="100" y2="90" stroke="#3498db" stroke-width="40" stroke-opacity="0.6"/>
  <line x1="150" y1="10" x2="150" y2="90" stroke="#2ecc71" stroke-width="40" stroke-opacity="1"/>
</svg>

CSSとの併用における優先順位

SVGのスタイル指定には以下の優先順位があります(高い順):

  1. インラインスタイル (style="fill: red;")
  2. プレゼンテーション属性 (fill="red")
  3. CSSルール (.shape { fill: red; })
<svg viewBox="0 0 200 100">
  <style>
    .circle { fill: blue; }
  </style>
  <!-- 最終的な色は赤(インラインスタイルが最優先) -->
  <circle class="circle" cx="50" cy="50" r="40" fill="green" style="fill: red;"/>
</svg>

この優先順位を理解することで、デバッグやスタイル管理がスムーズになります。

実践例: ダークモード対応のアイコン

<svg viewBox="0 0 100 100" class="theme-icon">
  <style>
    .theme-icon .icon-path {
      fill: #2c3e50;
      stroke: #34495e;
      stroke-width: 2;
      transition: fill 0.3s ease, stroke 0.3s ease;
    }

    @media (prefers-color-scheme: dark) {
      .theme-icon .icon-path {
        fill: #ecf0f1;
        stroke: #bdc3c7;
      }
    }
  </style>
  <path class="icon-path" d="M 50 20 L 80 80 L 20 80 Z"/>
</svg>

JavaScriptとの連携例

<svg id="interactive-circle" viewBox="0 0 100 100">
  <circle id="myCircle" cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

<script>
  const circle = document.getElementById('myCircle');

  // クリックで色を変更
  circle.addEventListener('click', () => {
    const currentFill = circle.getAttribute('fill');
    circle.setAttribute('fill', currentFill === '#3498db' ? '#e74c3c' : '#3498db');
  });

  // マウスオーバーで拡大
  circle.addEventListener('mouseenter', () => {
    circle.style.transform = 'scale(1.1)';
    circle.style.transformOrigin = 'center';
    circle.style.transition = 'transform 0.3s ease';
  });

  circle.addEventListener('mouseleave', () => {
    circle.style.transform = 'scale(1)';
  });
</script>

実際の表示

See the Pen svg-code-guide-15 by watashi-xyz (@watashi-xyz) on CodePen.

このセクションでは、<path>要素による複雑な図形の描画方法、レスポンシブ対応の実装テクニック、そしてfillstroke属性を使った高度なスタイリング手法を紹介しました。これらの知識を組み合わせることで、プロフェッショナルなSVGグラフィックスを自在に作成できるようになります。次のセクションでは、SVGコードの最適化とパフォーマンス向上のテクニックについて詳しく解説します。

格安ドメイン取得サービス─ムームードメイン─

SVGコードを最適化して軽量化・高パフォーマンス化する

デザインツールから書き出されたSVGコードには、多くの場合、冗長なメタデータや不要な属性が含まれています。このセクションでは、SVGコードを最適化し、ファイルサイズを削減しながら、表示パフォーマンスを向上させる実践的なテクニックを解説します。

SVGOMG・SVGOで不要なコードを削除する方法

SVGの最適化において、最も効果的かつ簡単な方法が、専用の最適化ツールを使用することです。SVGOMG(GUI版)とSVGO(CLI版)は、業界標準の最適化ツールとして広く使われています。

デザインツールが出力する冗長なコードの実態

Illustratorなどのデザインツールが出力するSVGには、以下のような不要な要素が含まれます:

最適化前のSVGコード例:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<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"
	 viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve">
<style type="text/css">
	.st0{fill:#3498DB;}
</style>
<circle class="st0" cx="50" cy="50" r="40"/>
<metadata>
	<sfw  xmlns="&ns_sfw;">
		<slices></slices>
		<sliceSourceBounds  bottomLeftOrigin="true" height="100" width="100" x="0" y="0"/>
	</sfw>
</metadata>
</svg>

最適化後のSVGコード:

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

削減された要素:

  1. XMLヘッダー(<?xml version...?>)
  2. コメント(Generator情報)
  3. 不要な属性(version, id, x, y, styleなど)
  4. xmlns:xlink名前空間(未使用の場合)
  5. メタデータタグ
  6. 内部スタイルシート(インライン化可能な場合)
  7. 不要な空白や改行

この例では、約450バイトから約100バイトへ、約78%のファイルサイズ削減が実現されています。

SVGOMGの使い方(ブラウザベースのGUIツール)

SVGOMGは、Jake Archibaldが開発したブラウザ上で動作する最適化ツールです。

アクセス方法: https://jakearchibald.github.io/svgomg/

基本的な使用手順:

  1. SVGファイルをドラッグ&ドロップまたは「Open SVG」ボタンからアップロード
  2. リアルタイムプレビューで最適化結果を確認
  3. 右側のオプションで最適化レベルを調整
  4. ダウンロードボタンでマークアップをコピーまたはファイル保存

推奨設定:

  • Precision: 2 (座標の小数点以下の桁数)
  • Remove viewBox: OFF (レスポンシブ対応のため必須)
  • Remove IDs: Selective (JavaScript連携がある場合はOFF)
  • Remove dimensions: ON (CSSで制御する場合)
  • Remove style elements: ON (外部CSSで管理する場合)
  • Remove comments: ON
  • Remove metadata: ON
  • Remove hidden elements: ON
  • Convert colors: Shorten (色コードを短縮)
  • Merge paths: ON (可能な場合にパスを統合)

注意すべきオプション:

  • Remove viewBox: 必ずOFFにするviewBoxはレスポンシブ対応に不可欠です
  • Remove IDs: JavaScriptでSVG要素を操作する予定がある場合は、このオプションをOFFにするか”Selective”に設定します
  • Precision: 通常は2が推奨です。1にするとさらに軽量化できますが、複雑な図形で歪みが発生する可能性があります

SVGOの使い方(Node.js CLIツール)

SVGOは、コマンドラインで動作する最適化ツールで、ビルドプロセスへの組み込みに適しています。

インストール(Node.js環境):

# グローバルインストール
npm install -g svgo

# プロジェクト単位でのインストール
npm install --save-dev svgo

基本的なコマンド:

# 単一ファイルの最適化
svgo input.svg -o output.svg

# フォルダ内の全SVGファイルを最適化
svgo -f ./icons -o ./icons-optimized

# 上書き最適化(元ファイルを置き換え)
svgo input.svg

設定ファイル(svgo.config.js)を使った高度な設定:

module.exports = {
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          // viewBoxを削除しない
          removeViewBox: false,
          // 不要な属性を削除
          removeUnknownsAndDefaults: true,
          // 空白を削除
          removeEmptyContainers: true,
          // パスを統合
          mergePaths: true,
          // 色を短縮形に変換
          convertColors: {
            shorthex: true,
            shortname: true
          }
        }
      }
    },
    // IDを特定のパターンで保持
    {
      name: 'removeAttrs',
      params: {
        attrs: '(stroke|fill)'
      }
    }
  ]
};

package.jsonへの組み込み:

{
  "scripts": {
    "optimize-svg": "svgo -f ./src/icons -o ./dist/icons --config=svgo.config.js"
  }
}

これにより、npm run optimize-svgで一括最適化が可能になります。

Webpackやビルドツールとの連携

Webpack使用時の設定例:

npm install --save-dev svgo-loader
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\\.svg$/,
        use: [
          {
            loader: 'svgo-loader',
            options: {
              plugins: [
                { removeViewBox: false },
                { removeEmptyAttrs: true }
              ]
            }
          }
        ]
      }
    ]
  }
};

Vite使用時の設定例:

npm install --save-dev vite-plugin-svgo
// vite.config.js
import { defineConfig } from 'vite';
import { svgo } from 'vite-plugin-svgo';

export default defineConfig({
  plugins: [
    svgo({
      plugins: [
        { name: 'removeViewBox', active: false },
        { name: 'removeEmptyAttrs', active: true }
      ]
    })
  ]
});

最適化の効果測定

実際のファイルサイズ比較例:

ファイル最適化前最適化後削減率
シンプルなアイコン2.1 KB0.4 KB81%
複雑なイラスト45 KB18 KB60%
ロゴ(グラデーション含む)8.5 KB3.2 KB62%

大規模なWebサイトで100個のSVGアイコンを使用している場合、最適化により数百KBの帯域幅削減が期待できます。

Illustratorの書き出し設定でクリーンなSVGを生成するコツ

デザインツール側で適切な書き出し設定を行うことで、後処理の手間を大幅に削減できます。ここでは、IllustratorとFigmaにおける推奨設定を解説します。

Adobe Illustratorの最適な書き出し設定

書き出し手順:

  1. ファイル > 書き出し > スクリーン用に書き出し を選択
  2. または ファイル > 別名で保存 > SVG を選択

SVGオプションダイアログの推奨設定:

【スタイル設定】
✓ スタイル: プレゼンテーション属性
  (外部CSSで管理する場合。インライン化する場合は「インラインスタイル」)

【フォント】
✓ フォント: SVG (またはアウトライン化)
  ※テキストを編集可能にする場合は「SVG」、図形として扱う場合は「アウトライン」

【画像】
✓ 画像: 埋め込み (または リンク)
  ※ファイルサイズを抑えたい場合は「リンク」、移植性を重視する場合は「埋め込み」

【オブジェクトID】
✓ オブジェクトID: レイヤー名
  (JavaScriptで操作する場合は「最小」より「レイヤー名」が推奨)

【小数点以下の桁数】
✓ 小数点以下の桁数: 2
  (精度とファイルサイズのバランスが良い)

【最適化】
✓ 最適化をCSSプロパティ: チェック
✓ 未使用グラフィックスタイルを削除: チェック
✓ レスポンシブ: チェック (width/heightを削除してviewBoxのみにする)

特に重要な設定:

  1. 「レスポンシブ」にチェック:
    これによりwidthheight属性が削除され、viewBoxのみが保持されます。CSS側でサイズ制御が可能になります。
  2. 「スタイル: プレゼンテーション属性」:
    内部<style>タグではなく、各要素に直接fillstroke属性として出力されます。これにより、外部CSSでスタイルを上書きしやすくなります。
  3. アートボードの活用:
    複数のアイコンを一度に書き出す場合、各アイコンを個別のアートボードに配置し、「各アートボードを個別のファイルに書き出し」を選択します。

アウトライン化の判断基準

テキストをアウトライン化すべきケース:

  • ロゴやブランディング要素(フォントの完全な再現が必要)
  • 特殊なフォントを使用している
  • テキストの編集が不要

テキストをアウトライン化すべきでないケース:

  • アクセシビリティが重要(スクリーンリーダー対応)
  • SEO対策でテキストを検索可能にしたい
  • 多言語対応で後からテキスト変更の可能性がある

アウトライン化のコマンド: 選択ツールでテキストを選択 → 書式 > アウトラインを作成 (Ctrl+Shift+O / Cmd+Shift+O)

Figmaの最適な書き出し設定

Figmaは比較的クリーンなSVGを出力しますが、以下の設定で更に最適化できます。

書き出し手順:

  1. レイヤーまたはフレームを選択
  2. 右パネルの「Export」セクションで「+」をクリック
  3. フォーマットを「SVG」に選択
  4. 「Export」ボタンをクリック

Figmaの書き出し設定:

【Include "id" attribute】
デフォルト: ON
推奨: JavaScript操作が不要な場合はOFF
(IDを削除することでファイルサイズを削減)

【Outline text】
デフォルト: OFF
推奨: ロゴやアイコンの場合はON、編集可能なテキストの場合はOFF

【Simplify stroke】
デフォルト: ON
推奨: 常にON
(複雑なストロークをシンプルなパスに変換)

Figmaプラグインでの高度な最適化:

  • SVGO Compressor: Figma内でSVGOを実行できるプラグイン
  • Export with Optimize: 書き出し時に自動で最適化

Sketchの推奨設定

書き出し設定:

✓ Export → SVG
✓ Flatten bitmaps: チェック (ラスター画像を埋め込む場合)
✓ 属性: presentation attributes を選択
✓ IDを含める: JavaScript連携がある場合のみチェック

デザインツール共通のベストプラクティス

  1. 不要なレイヤーを削除:
    非表示レイヤーや空のグループはSVGに含まれることがあります
  2. パスの統合:
    同じ色・スタイルの複数のパスは、事前に統合しておくとコードが簡潔になります
  3. 不要なアンカーポイントを削除:
    パスを簡略化することでコードサイズが削減されます(Illustrator: オブジェクト > パス > 単純化)
  4. グリッドに整列:
    座標を整数値にすることで、小数点以下の桁数を削減できます

base64エンコードでCSSやHTMLに直接埋め込む手順

SVGをBase64エンコードして埋め込むことで、HTTPリクエスト数を削減できます。ただし、適切な使いどころを理解することが重要です。

Base64エンコードのメリットとデメリット

メリット:

  1. HTTPリクエストの削減:
    外部ファイルとして読み込む必要がなくなります
  2. 初期表示の高速化:
    HTML/CSSと一緒にダウンロードされるため、追加の読み込み待ちが発生しません
  3. デプロイの簡素化:
    画像ファイルを別途管理する必要がありません

デメリット:

  1. ファイルサイズの増加:
    Base64エンコードにより、元のSVGより約33%サイズが増加します
  2. キャッシュ効率の低下:
    CSS/HTML全体がキャッシュされるため、SVG単体の更新時にも全体を再ダウンロード
  3. 可読性の低下:
    エンコードされたコードは人間が読めません
  4. メンテナンス性の低下:
    後から編集する際、デコード→編集→エンコードの手順が必要

Base64エンコードが適しているケース

  • 小さなアイコン(1KB以下)
  • クリティカルCSSに含めて初期表示を高速化したい場合
  • 単一ページアプリケーション(SPA)でHTTPリクエストを最小化したい場合
  • メールHTMLなど外部ファイル参照ができない環境

Base64エンコードが適さないケース

  • 大きなイラスト(5KB以上)
  • 頻繁に更新される画像
  • 複数のページで再利用される画像(外部ファイルとしてキャッシュする方が効率的)

Base64エンコードの実装方法

方法1: オンラインツールを使用

以下のようなWebサービスで簡単にエンコード可能:

方法2: Node.jsでエンコード

const fs = require('fs');

// SVGファイルを読み込み
const svgContent = fs.readFileSync('icon.svg', 'utf8');

// Base64エンコード
const base64 = Buffer.from(svgContent).toString('base64');

// Data URI形式で出力
const dataUri = `data:image/svg+xml;base64,${base64}`;

console.log(dataUri);

方法3: Webpackでの自動化

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\\.svg$/,
        type: 'asset/inline', // 自動的にBase64エンコード
        parser: {
          dataUrlCondition: {
            maxSize: 2 * 1024 // 2KB以下のSVGのみインライン化
          }
        }
      }
    ]
  }
};

CSSのbackground-imageでの使用例

Base64エンコードされたSVG:

.icon {
  width: 24px;
  height: 24px;
  background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj4KICA8Y2lyY2xlIGN4PSI1MCIgY3k9IjUwIiByPSI0MCIgZmlsbD0iIzM0OThkYiIvPgo8L3N2Zz4=);
  background-size: contain;
  background-repeat: no-repeat;
}

より効率的な方法: URLエンコード(非Base64)

実は、SVGの場合、Base64よりもURLエンコードの方が効率的です。

URLエンコード版:

.icon {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='<http://www.w3.org/2000/svg>' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='40' fill='%233498db'/%3E%3C/svg%3E");
}

URLエンコードのメリット:

  • Base64よりファイルサイズが小さい(約33%の増加がない)
  • gzip圧縮との相性が良い

JavaScriptでURLエンコード:

const svgContent = `<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>`;

const encodedSvg = encodeURIComponent(svgContent)
  .replace(/'/g, '%27')
  .replace(/"/g, '%22');

const dataUri = `data:image/svg+xml,${encodedSvg}`;

Sassでの自動化

@function svg-url($svg) {
  @return url("data:image/svg+xml,#{$svg}");
}

// 使用例
.icon {
  background-image: svg-url("<svg xmlns='<http://www.w3.org/2000/svg>' viewBox='0 0 24 24'><path d='M12 2L2 7v10c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V7l-10-5z' fill='%23333'/></svg>");
}

実際の使用例: CSSスプライト的な活用

/* 複数のアイコンをCSS変数で管理 */
:root {
  --icon-check: url("data:image/svg+xml,%3Csvg xmlns='<http://www.w3.org/2000/svg>' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z' fill='%232ecc71'/%3E%3C/svg%3E");

  --icon-error: url("data:image/svg+xml,%3Csvg xmlns='<http://www.w3.org/2000/svg>' viewBox='0 0 24 24'%3E%3Cpath d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z' fill='%23e74c3c'/%3E%3C/svg%3E");
}

.message-success::before {
  content: '';
  display: inline-block;
  width: 20px;
  height: 20px;
  background-image: var(--icon-check);
}

.message-error::before {
  content: '';
  display: inline-block;
  width: 20px;
  height: 20px;
  background-image: var(--icon-error);
}

パフォーマンスの最終判断

推奨事項:

ファイルサイズ推奨方法理由
500バイト未満URLエンコードで埋め込みHTTPリクエスト削減のメリットが大きい
500バイト〜2KB状況に応じて判断使用頻度が高ければ外部ファイル
2KB以上外部ファイル+キャッシュキャッシュ効率を優先

最適化を行う際は、実際のネットワーク環境でパフォーマンスを測定し、プロジェクトの要件に応じて最適な方法を選択することが重要です。次のセクションでは、SVGが正しく表示されない場合のトラブルシューティングとアクセシビリティ対応について詳しく解説します。

トラブル対策と応用編:正しく表示されないときのチェックポイント

SVGコードを実装した際に「期待通りに表示されない」「サイズがおかしい」といった問題に直面することは珍しくありません。このセクションでは、よくあるトラブルの原因と解決方法、そしてアクセシビリティやSEOを考慮した実装方法について詳しく解説します。

ブラウザでSVGが崩れる・スケーリングされない原因と対処法

SVGの表示トラブルの多くは、viewBoxwidthheightの関係性や、CSSとの競合が原因です。それぞれのケースを具体的に見ていきましょう。

トラブル1: SVGのサイズが0pxになって表示されない

症状: SVGが全く表示されない、またはブラウザの検証ツールで見るとサイズが0×0pxになっている。

原因:widthheight属性が指定されておらず、viewBoxのみが定義されている状態で、CSSでもサイズが指定されていない。

問題のあるコード:

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

ブラウザによっては、viewBoxだけでは描画サイズが決定できず、0pxとして扱われます。

解決方法1: width/height属性を追加

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100" width="100" height="100">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

解決方法2: CSSでサイズを指定

<style>
  .my-svg {
    width: 100px;
    height: 100px;
    /* または */
    width: 100%;
    height: auto;
  }
</style>

<svg class="my-svg" xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

解決方法3: インラインスタイルで指定

<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100" style="width: 100px; height: 100px;">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

トラブル2: viewBoxwidth/heightの不整合でアスペクト比が崩れる

症状: 円が楕円になったり、正方形が長方形に変形したりする。

原因:viewBoxのアスペクト比と、実際のwidth/heightのアスペクト比が異なる。

問題のあるコード:

<!-- viewBoxは1:1の正方形だが、実サイズは2:1の長方形 -->
<svg viewBox="0 0 100 100" width="200" height="100">
  <circle cx="50" cy="50" r="40" fill="#e74c3c"/>
</svg>

この場合、円が横に引き伸ばされて楕円になります。

解決方法1: preserveAspectRatioを適切に設定

<!-- アスペクト比を保持して中央配置(デフォルト) -->
<svg viewBox="0 0 100 100" width="200" height="100" preserveAspectRatio="xMidYMid meet">
  <circle cx="50" cy="50" r="40" fill="#e74c3c"/>
</svg>

この設定により、円は正円のまま維持され、左右に余白ができます。

解決方法2: viewBoxと実サイズのアスペクト比を一致させる

<!-- 両方を2:1にする -->
<svg viewBox="0 0 200 100" width="200" height="100">
  <circle cx="100" cy="50" r="40" fill="#e74c3c"/>
</svg>

解決方法3: heightをautoにしてアスペクト比を自動調整

<svg viewBox="0 0 100 100" width="200" height="auto">
  <circle cx="50" cy="50" r="40" fill="#e74c3c"/>
</svg>

これにより、widthが200pxで、heightが自動的に200pxになります。

トラブル3: 親要素のサイズにフィットしない

症状:width="100%"を指定してもレスポンシブに動作しない、または親要素からはみ出す。

原因: SVGにdisplay: inline(デフォルト)が適用されているため、インライン要素特有の余白が発生する。

問題のあるコード:

<div style="width: 300px; background: #f0f0f0;">
  <svg viewBox="0 0 100 100" width="100%" height="auto">
    <rect width="100" height="100" fill="#3498db"/>
  </svg>
</div>

この場合、SVGの下に約4pxの謎の余白が発生します。

解決方法1: display: blockを適用

svg {
  display: block;
  width: 100%;
  height: auto;
}

解決方法2: 親要素にline-height: 0を設定

.svg-container {
  line-height: 0;
}

解決方法3: vertical-alignを調整

svg {
  vertical-align: top; /* または middle、bottom */
}

トラブル4: CSSのmax-widthが効かない

症状:max-width: 100%を指定してもSVGが親要素からはみ出す。

原因: SVGのwidth属性がCSSよりも優先されている、またはheightが固定値で指定されている。

問題のあるコード:

<style>
  .responsive-svg {
    max-width: 100%;
    height: auto;
  }
</style>

<svg class="responsive-svg" viewBox="0 0 500 500" width="500" height="500">
  <circle cx="250" cy="250" r="200" fill="#9b59b6"/>
</svg>

解決方法1: widthheight属性を削除

<svg class="responsive-svg" viewBox="0 0 500 500">
  <circle cx="250" cy="250" r="200" fill="#9b59b6"/>
</svg>
.responsive-svg {
  width: 100%;
  max-width: 500px;
  height: auto;
  display: block;
}

解決方法2: CSSで明示的に上書き

.responsive-svg {
  width: 100% !important;
  height: auto !important;
  max-width: 500px;
  display: block;
}

トラブル5: <img>タグで読み込んだSVGにCSSが効かない

症状: 外部CSSでSVGの色やスタイルを変更しようとしても反映されない。

原因:<img>タグで読み込んだSVGは、完全に独立した文書として扱われるため、親ページのCSSは適用されません。

問題のあるコード:

<style>
  .icon circle {
    fill: red; /* これは効かない */
  }
</style>

<img class="icon" src="icon.svg" alt="アイコン">

解決方法1: SVGをインラインで埋め込む

<style>
  .icon circle {
    fill: red; /* これは効く */
  }
</style>

<svg class="icon" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40"/>
</svg>

解決方法2: CSS変数を使った動的な色変更

SVGファイル内でCSS変数を定義:

<!-- icon.svg -->
<svg xmlns="<http://www.w3.org/2000/svg>" viewBox="0 0 100 100">
  <style>
    circle {
      fill: var(--icon-color, #3498db);
    }
  </style>
  <circle cx="50" cy="50" r="40"/>
</svg>

しかし、<img>タグでは依然として変数を渡せないため、インライン化が最善策です。

解決方法3: <object>タグを使用してJavaScriptで操作

<object id="svg-object" data="icon.svg" type="image/svg+xml"></object>

<script>
  const svgObject = document.getElementById('svg-object');
  svgObject.addEventListener('load', () => {
    const svgDoc = svgObject.contentDocument;
    const circle = svgDoc.querySelector('circle');
    circle.setAttribute('fill', 'red');
  });
</script>

トラブル6: Safari でviewBoxが機能しない

症状: SafariでだけSVGのスケーリングがおかしい。

原因: 古いバージョンのSafariでは、viewBoxのみの指定では正しく表示されないバグがあります。

解決方法: widthheightを併記

<svg viewBox="0 0 100 100" width="100%" height="100%">
  <circle cx="50" cy="50" r="40" fill="#2ecc71"/>
</svg>

トラブル7: Internet Explorer 11 での表示問題

症状: IE11でSVGが正しく表示されない、またはレスポンシブに動作しない。

原因: IE11は多くのSVG機能が不完全で、特にheight: autoが効きません。

解決方法: パディングハックを使用

<style>
  .svg-wrapper {
    position: relative;
    width: 100%;
    padding-bottom: 100%; /* アスペクト比1:1の場合 */
    height: 0;
    overflow: hidden;
  }

  .svg-wrapper svg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
</style>

<div class="svg-wrapper">
  <svg viewBox="0 0 100 100">
    <circle cx="50" cy="50" r="40" fill="#f39c12"/>
  </svg>
</div>

デバッグのための実践的なチェックリスト

SVGが期待通りに表示されない場合、以下の順序で確認してください:

1. ブラウザの開発者ツールで検証

- SVGのサイズ(width × height)が0pxになっていないか
- viewBoxの値が適切か
- CSSが意図通り適用されているか

2. 最小限の構成で動作確認

<!-- シンプルなテストコード -->
<svg viewBox="0 0 100 100" width="100" height="100" style="border: 1px solid red;">
  <rect width="100" height="100" fill="blue"/>
</svg>

これが表示されれば、SVGの基本構造は正しいということがわかります。

3. コンソールエラーを確認

  • XML構文エラー(閉じタグの欠落など)
  • 名前空間の問題
  • 不正な属性値

4. バリデーションツールで検証

アクセシビリティ対応(<title>・<desc>・role属性の使い方)

SVGをアクセシブルにすることは、すべてのユーザーにコンテンツを届けるために不可欠です。スクリーンリーダーユーザーや、視覚に障害のあるユーザーにも配慮した実装を行いましょう。

SVGのアクセシビリティにおける基本概念

SVGは画像として扱われるため、適切なテキスト代替が必要です。HTMLの<img>タグにalt属性があるように、SVGには<title><desc>要素があります。

装飾的なSVGの場合

装飾的なSVG(情報を伝えない、視覚的な装飾のみ)は、スクリーンリーダーから隠すべきです。

実装方法:

<!-- パターン1: aria-hidden を使用 -->
<svg aria-hidden="true" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

<!-- パターン2: role="presentation" を使用 -->
<svg role="presentation" viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db"/>
</svg>

<!-- パターン3: 空のalt属性(imgタグの場合) -->
<img src="decorative.svg" alt="">

使い分け:

  • aria-hidden="true": 完全に支援技術から隠す(推奨)
  • role="presentation": セマンティックな意味を削除するが、完全には隠さない

意味のあるSVGの場合

情報を伝えるSVG(アイコン、グラフ、図表など)には、適切な説明を付加します。

基本パターン: <title>のみ

<svg viewBox="0 0 100 100" role="img" aria-labelledby="icon-title">
  <title id="icon-title">ユーザープロフィールアイコン</title>
  <circle cx="50" cy="30" r="15" fill="#3498db"/>
  <path d="M 30 70 Q 50 50 70 70" fill="#3498db"/>
</svg>

解説:

  • role="img": SVGを画像として扱うことを明示
  • aria-labelledby="icon-title": どの要素がラベルかを指定
  • <title>: 短い説明(HTMLのalt属性相当)

拡張パターン: <title><desc>の併用

複雑な図表やグラフの場合、詳細な説明が必要です。

<svg viewBox="0 0 400 300" role="img" aria-labelledby="chart-title chart-desc">
  <title id="chart-title">2024年第1四半期売上グラフ</title>
  <desc id="chart-desc">
    1月の売上は200万円、2月は250万円、3月は300万円と、
    前月比で順調に増加しています。
  </desc>

  <!-- グラフの描画 -->
  <rect x="50" y="100" width="80" height="150" fill="#3498db"/>
  <rect x="150" y="50" width="80" height="200" fill="#2ecc71"/>
  <rect x="250" y="0" width="80" height="250" fill="#f39c12"/>
</svg>

実際の表示

See the Pen Untitled by watashi-xyz (@watashi-xyz) on CodePen.

インタラクティブなSVGの場合

クリック可能なSVGやボタンとして機能するSVGには、追加の配慮が必要です。

ボタンとして機能するSVG:

<button type="button" aria-label="メニューを開く">
  <svg viewBox="0 0 100 100" aria-hidden="true">
    <title>ハンバーガーメニュー</title>
    <rect y="20" width="100" height="15" fill="#333"/>
    <rect y="45" width="100" height="15" fill="#333"/>
    <rect y="70" width="100" height="15" fill="#333"/>
  </svg>
</button>

この例では:

  • <button>要素にaria-labelで説明を付与
  • SVG自体はaria-hidden="true"で隠す(ボタンのラベルで説明済みのため)

リンクとして機能するSVG:

<a href="/profile" aria-label="プロフィールページへ移動">
  <svg viewBox="0 0 100 100" aria-hidden="true">
    <circle cx="50" cy="30" r="20" fill="#3498db"/>
    <path d="M 20 80 Q 50 60 80 80" fill="#3498db"/>
  </svg>
</a>

フォーカス管理

キーボード操作をサポートする場合、適切なフォーカス管理が必要です。

<style>
  .focusable-svg:focus {
    outline: 2px solid #3498db;
    outline-offset: 2px;
  }
</style>

<svg class="focusable-svg" tabindex="0" role="button"
     aria-label="いいねボタン" viewBox="0 0 100 100">
  <title>いいね</title>
  <path d="M50,90 L20,60 Q10,50 20,40 T50,30 T80,40 Q90,50 80,60 Z" fill="#e74c3c"/>
</svg>

<script>
  const svg = document.querySelector('.focusable-svg');

  // Enterキーとスペースキーでクリック動作
  svg.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault();
      svg.click();
    }
  });
</script>

言語と方向性

SVGにテキストが含まれる場合、言語と方向性を指定します。

<svg lang="ja" viewBox="0 0 200 100">
  <title>サンプルテキスト</title>
  <text x="10" y="50" font-size="20">こんにちは</text>
</svg>

<!-- アラビア語などRTL言語の場合 -->
<svg lang="ar" dir="rtl" viewBox="0 0 200 100">
  <title>مثال النص</title>
  <text x="190" y="50" font-size="20" text-anchor="end">مرحبا</text>
</svg>

色のコントラスト

WCAG 2.1基準に準拠したコントラスト比を確保します。

最低基準:

  • 通常のテキスト: 4.5:1以上
  • 大きなテキスト(18pt以上): 3:1以上
  • UIコンポーネント: 3:1以上
<!-- 良い例: 十分なコントラスト -->
<svg viewBox="0 0 200 100">
  <rect width="200" height="100" fill="#ffffff"/>
  <text x="10" y="50" font-size="24" fill="#000000">高コントラスト</text>
</svg>

<!-- 悪い例: 不十分なコントラスト -->
<svg viewBox="0 0 200 100">
  <rect width="200" height="100" fill="#f0f0f0"/>
  <text x="10" y="50" font-size="24" fill="#cccccc">低コントラスト</text>
</svg>

コントラスト比の確認には以下のツールが便利です:

アクセシビリティチェックリスト

実装時には以下を確認してください:

  • 装飾的なSVGには aria-hidden=”true” を付与
  • 意味のあるSVGには適切な <title> を提供
  • 複雑な図には <desc> で詳細説明を追加
  • role=”img” と aria-labelledby を適切に使用
  • インタラクティブな要素にはキーボード操作を実装
  • フォーカス可能な要素には視覚的なフォーカス表示
  • 色のコントラスト比が基準を満たしている
  • スクリーンリーダーでテスト(NVDA、JAWS、VoiceOverなど)

SEOやパフォーマンス面でのSVG活用の注意点

SVGを適切に活用することで、SEOとパフォーマンスの両面でメリットを得られます。ここでは、最適な実装方法を解説します。

SEO対策としてのSVG活用

インラインSVGがSEOに有利な理由:

テキストコンテンツとしてインデックス:
SVG内の<text>要素や<title><desc>は、検索エンジンにテキストとして認識されます。

<svg viewBox="0 0 400 100">
  <title>Web制作会社ロゴ - 株式会社サンプル</title>
  <text x="50" y="60" font-size="32" fill="#2c3e50">株式会社サンプル</text>
  <desc>東京を拠点とするWebデザイン・開発会社</desc>
</svg>

構造化データとの相性:
Schema.orgのマークアップと組み合わせることで、リッチスニペット表示の可能性が高まります。

<div itemscope itemtype="<https://schema.org/Organization>">
  <svg viewBox="0 0 200 100">
    <title itemprop="name">株式会社サンプル</title>
    <!-- ロゴの描画 -->
  </svg>
  <meta itemprop="url" content="<https://example.com>">
</div>

外部SVGファイルのSEO対策:

<img>タグで読み込む場合も、適切な属性を付与します。

<!-- 良い例 -->
<img src="logo.svg"
     alt="株式会社サンプル - Web制作会社"
     width="200"
     height="100">

<!-- さらに良い例: 構造化データと併用 -->
<img src="logo.svg"
     alt="株式会社サンプル"
     itemprop="logo"
     width="200"
     height="100">

alt属性の代わりに<title>を使う理由

HTMLの<img>タグにはalt属性がありますが、インラインSVGにはalt属性は存在しません。代わりに以下を使用します:

比較表:

要素HTML <img>インライン <svg>
短い説明alt="説明"<title>説明</title>
詳細説明longdesc(廃止)<desc>詳細</desc>
スクリーンリーダー対応自動aria-labelledbyが必要

実装例の対比:

<!-- HTML画像 -->
<img src="chart.png" alt="2024年売上推移グラフ">

<!-- SVG画像(同等の実装) -->
<svg role="img" aria-labelledby="chart-title">
  <title id="chart-title">2024年売上推移グラフ</title>
  <!-- グラフの描画 -->
</svg>

パフォーマンス最適化のベストプラクティス

1. ファイルサイズの最小化

<!-- 悪い例: 冗長なコード -->
<svg viewBox="0 0 100.000 100.000">
  <circle cx="50.000" cy="50.000" r="40.000"
          fill="rgb(52, 152, 219)"
          stroke="rgb(41, 128, 185)"
          stroke-width="2.000"/>
</svg>

<!-- 良い例: 最適化されたコード -->
<svg viewBox="0 0 100 100">
  <circle cx="50" cy="50" r="40" fill="#3498db" stroke="#2980b9" stroke-width="2"/>
</svg>

2. 複雑なSVGの遅延読み込み

<img src="complex-illustration.svg"
     alt="詳細なイラスト"
     loading="lazy"
     width="800"
     height="600">

loading="lazy"属性により、画面に表示される直前まで読み込みが遅延され、初期表示が高速化されます。

3. CSSアニメーションの負荷に注意

避けるべき重い処理:

/* 悪い例: filter はGPU負荷が高い */
.svg-icon {
  filter: drop-shadow(0 4px 8px rgba(0,0,0,0.3));
  transition: filter 0.3s;
}

.svg-icon:hover {
  filter: drop-shadow(0 8px 16px rgba(0,0,0,0.5));
}

推奨される軽量な処理:

/* 良い例: transform は GPU アクセラレーション対応 */
.svg-icon {
  transition: transform 0.3s;
  will-change: transform; /* GPU処理を促進 */
}

.svg-icon:hover {
  transform: scale(1.1);
}

4. 大量のSVGアイコンの管理

スプライトシートの活用:

<!-- SVGスプライト定義 -->
<svg style="display: none;">
  <defs>
    <symbol id="icon-home" viewBox="0 0 24 24">
      <path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z"/>
    </symbol>
    <symbol id="icon-user" viewBox="0 0 24 24">
      <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
    </symbol>
  </defs>
</svg>

<!-- アイコンの使用 -->
<svg class="icon" aria-labelledby="home-title">
  <title id="home-title">ホーム</title>
  <use href="#icon-home"/>
</svg>

<svg class="icon" aria-labelledby="user-title">
  <title id="user-title">ユーザー</title>
  <use href="#icon-user"/>
</svg>

メリット:

  • 同じアイコンを複数回使用してもHTMLが肥大化しない
  • ブラウザのキャッシュが効率的に働く
  • メンテナンスが容易

5. HTTPリクエストの最適化

戦略的な埋め込み判断:

サイズ使用頻度推奨方法理由
1KB未満インライン埋め込みHTTPリクエスト削減
1-5KB外部ファイル+キャッシュ複数ページで再利用
5KB以上外部ファイル+遅延読み込み初期表示の高速化
複雑なアニメーション外部ファイルメンテナンス性向上

6. Service Workerでのキャッシュ戦略

// service-worker.js
self.addEventListener('fetch', (event) => {
  if (event.request.url.endsWith('.svg')) {
    event.respondWith(
      caches.open('svg-cache-v1').then((cache) => {
        return cache.match(event.request).then((response) => {
          return response || fetch(event.request).then((fetchResponse) => {
            cache.put(event.request, fetchResponse.clone());
            return fetchResponse;
          });
        });
      })
    );
  }
});

これにより、SVGファイルが効率的にキャッシュされ、2回目以降の読み込みが高速化されます。

Core Web Vitalsへの影響と対策

Googleの検索ランキング要因となるCore Web Vitalsに、SVGの実装は影響します。

1. LCP (Largest Contentful Paint) の改善

ファーストビューに大きなSVGがある場合:

<!-- 優先度を上げる -->
<link rel="preload" as="image" href="hero-illustration.svg" type="image/svg+xml">

<img src="hero-illustration.svg"
     alt="メインビジュアル"
     fetchpriority="high"
     width="1200"
     height="600">

2. CLS (Cumulative Layout Shift) の防止

SVG読み込み時のレイアウトシフトを防ぐため、必ずwidthheightを指定:

<!-- 悪い例: サイズ未指定でレイアウトシフト発生 -->
<img src="logo.svg" alt="ロゴ">

<!-- 良い例: サイズ指定でレイアウト確保 -->
<img src="logo.svg" alt="ロゴ" width="200" height="50">

<!-- さらに良い例: aspect-ratioで柔軟性も確保 -->
<img src="logo.svg" alt="ロゴ" width="200" height="50" style="aspect-ratio: 4/1;">

3. FID (First Input Delay) の改善

複雑なSVGアニメーションはメインスレッドをブロックする可能性があります:

// 悪い例: requestAnimationFrame で重い処理
function animateSVG() {
  // 複雑な計算...
  requestAnimationFrame(animateSVG);
}

// 良い例: CSS アニメーションを優先
/* CSSアニメーションはGPUアクセラレーション対応 */
@keyframes rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.animated-svg {
  animation: rotate 2s linear infinite;
}

モバイルパフォーマンスの考慮

モバイルデバイスでは、CPUとGPUの性能が限られているため、特別な配慮が必要です。

1. 複雑度の制限

<!-- 悪い例: 数千のパスを含む超複雑なSVG -->
<svg viewBox="0 0 1000 1000">
  <!-- 3000個以上のpath要素... -->
</svg>

<!-- 良い例: 簡略化されたバージョンを用意 -->
<picture>
  <source media="(max-width: 768px)" srcset="illustration-simple.svg">
  <img src="illustration-detailed.svg" alt="イラスト">
</picture>

2. フィルター効果の使用を控える

/* モバイルでは無効化 */
@media (max-width: 768px) {
  .svg-with-filter {
    filter: none; /* blur や drop-shadow は重い */
  }
}

パフォーマンス測定ツール

実装後は必ず測定を行いましょう:

Chrome DevTools – Performance タブ:

  1. Ctrl+Shift+P (Mac: Cmd+Shift+P)
  2. “Show Performance” を入力
  3. 記録ボタンをクリックしてページ操作
  4. SVGのレンダリング時間を確認

Lighthouse での測定:

  1. Chrome DevTools を開く
  2. Lighthouse タブを選択
  3. パフォーマンス、アクセシビリティにチェック
  4. “Analyze page load” を実行

WebPageTest:

実践的な最適化フロー

  1. SVGコードの最適化 (SVGO使用)
  2. 適切な埋め込み方法の選択
    • 小さいアイコン → インライン
    • 大きな画像 → 外部ファイル
  3. アクセシビリティ対応
    • title/desc の追加
    • role と aria 属性の設定
  4. レスポンシブ対応
    • viewBox の適切な設定
    • CSS での柔軟なサイズ制御
  5. パフォーマンス測定
    • Lighthouse でスコア確認
    • 問題があれば手順1に戻る
  6. 本番環境へのデプロイ
    • CDN配信の検討
    • HTTP/2 の活用
Webデザインコース

よくある質問(FAQ)

SVGを外部ファイルとして読み込むべきか、インラインコードとしてHTMLに直接記述すべきか?

A1: 利用シーンと目的によります。

インラインSVG

メリット

  1. HTTPリクエスト不要: 通信回数が減り、表示が高速化(パフォーマンス向上)。
  2. CSS/JSによる操作が容易: fillやstroke、アニメーションをCSS/JSで制御しやすい。

デメリット

  1. HTMLのファイルサイズが増大: 特に大きなSVGを多用すると、HTMLのダウンロード時間が長くなる。
  2. キャッシュが効きにくい: HTMLのキャッシュに依存するため、個別のSVGの再利用性が低い。

推奨される利用シーン

  • アイコン、ロゴ、サイト内で頻繁に利用し、CSSで色を変えたい要素。

外部ファイル(やbackground-image)

メリット

  1. キャッシュが効く: ブラウザによってキャッシュされ、再利用性が高い。
  2. HTMLがクリーン: HTMLコードの肥大化を防げる。

デメリット

  1. HTTPリクエストが発生: 通信オーバーヘッドが生じる。
  2. CSS/JSでの操作が制限: タグの場合、CSSのfill/strokeで内部要素のスタイルを直接変更できない。

推奨される利用シーン

  • 大きなイラスト、複雑な図、ページ内で一度しか使わない要素。

結論: アイコンやロゴはインライン複雑な図版は外部ファイル(または<object>/<iframe>)で使い分けるのが一般的です。


既存のPNG/JPG画像をSVGに変換することは可能ですか?

技術的には可能ですが、品質は元の画像形式に依存します。

PNGやJPGはラスター形式(ピクセル情報)であるため、これをベクター形式であるSVGに変換するプロセスは「トレース」や「ベクター化」と呼ばれます。

  • 単色・シンプルなロゴ:
    Adobe Illustratorの「画像トレース」機能や、などのオンラインツールを使えば、比較的きれいに変換できます。
  • 写真・複雑なイラスト:
    写真のようなグラデーションや多数の色を持つラスター画像をSVGに変換しても、ファイルサイズが膨大になるか、ディテールが失われ、期待するSVGのメリット(軽さ、滑らかさ)は得られません。

注意点: 変換されたSVGコードは、デザインツールで作成されたものよりも冗長になりやすいため、SVGOMGなどでの最適化が必須です。

SVGアニメーションを実現する最適な方法は何ですか?

主に3つの方法があり、目的によって使い分けます。

方法特徴メリットデメリット
CSSアニメーションtransform, opacity, fill, strokeなどのCSSプロパティを使用。記述が容易で、ブラウザのレンダリングが高速。Webデザイナーに最も馴染み深い。viewBoxの変更やパスの変形など、複雑なアニメーションには不向き。
JavaScript (Web Animation API/ライブラリ)GSAPLottieなどのライブラリを使用。パスの変形(モーフィング)や複雑なシーケンス制御など、高度な表現が可能。ライブラリの読み込みが必要。
SMIL (Synchronized Multimedia Integration Language)SVGコード内に<animate><set>などのタグを直接記述。SVG単体で完結し、外部ファイルが不要。IE/Edgeなど一部ブラウザのサポートが限定的で、非推奨の傾向にある。

推奨: 単純なアニメーションはCSS複雑なものはGSAPやLottie(特にデザイナーがAfter Effectsで作成する場合)を使うのが、現在のWeb開発の主流です。SVGコード内のアニメーションプロパティ(例: fill)をCSSの@keyframesで操作することを、まず試してみてください。

まとめ

この記事では、SVGコードの書き方について、基礎から実践的なテクニックまで網羅的に解説してきました。SVGはベクター形式の画像として、拡大しても劣化しない特性を持ち、現代のWeb制作において欠かせない技術となっています。

重要ポイント

  • viewBoxの理解が最重要:
    SVGの座標系を定義するviewBoxを正しく設定することで、レスポンシブ対応がスムーズに実現できます。widthheightとの関係性を理解しましょう。
  • <path>要素で表現力が格段に向上:
    M、L、Cなどのパスコマンドをマスターすれば、複雑な図形も自在に描けます。特にベジェ曲線(Cコマンド)は頻繁に使用します。
  • 最適化は必須プロセス:
    SVGOMGやSVGOを使って不要なコードを削除することで、ファイルサイズを60〜80%削減できます。デザインツールの書き出し設定も重要です。
  • アクセシビリティを忘れずに:
    装飾的なSVGにはaria-hidden="true"、意味のあるSVGには<title>role="img"を設定しましょう。すべてのユーザーに配慮した実装が求められます。
  • パフォーマンスとSEOの両立:
    小さなアイコンはインライン埋め込み、大きな画像は外部ファイル化してキャッシュを活用します。loading="lazy"による遅延読み込みも効果的です。

SVGコードを正しく書くことで、美しく軽量、そしてアクセシブルなWebサイトを構築できます。本記事で学んだテクニックを実践し、ユーザー体験の向上とパフォーマンス改善を実現してください。トラブルが発生した際は、チェックリストを活用して一つずつ確認していけば、必ず解決できるはずです。

現役エンジニアのパーソナルメンターからマンツーマンで学べるテックアカデミー
タイトルとURLをコピーしました