塗り・線・グラデ・フィルタ
fill / stroke の細かい属性、線形 / 放射グラデ、パターン、フィルタ(blur / shadow / 色変換)、 clipPath / mask まで。
fill の指定
- 色名 / 16 進 / RGB / HSL / OKLCH
none: 塗らないcurrentColor: CSS の color を継承url(#gradient): グラデーション参照url(#pattern): パターン参照
fill-rule
path に穴がある時、どこを「内側」とみなすか:
- nonzero(既定)— 巻き数で判定
- evenodd — 奇数回横切れば内側
stroke の細かい属性
| 属性 | 値 |
|---|---|
| stroke | 色 / url / none / currentColor |
| stroke-width | 太さ(数値) |
| stroke-opacity | 0〜1 |
| stroke-linecap | butt / round / square |
| stroke-linejoin | miter / round / bevel / arcs(SVG 2) |
| stroke-miterlimit | miter の制限(既定 4) |
| stroke-dasharray | 破線パターン |
| stroke-dashoffset | 破線の開始位置 |
| vector-effect | non-scaling-stroke で太さ固定 |
linecap / linejoin
linecap:
butt ▬ 端が直角
round ● 端が丸
square ▣ 端が角張る + はみ出る
linejoin:
miter ◢ 鋭角(既定)
round ◐ 丸い結合
bevel ◣ 面取り
stroke-dasharray / dashoffset
<line stroke-dasharray="5 3" /> <!-- 5 描画 + 3 空白 -->
<line stroke-dasharray="2 2 6 2" /> <!-- 4 種パターン繰り返し -->
パスを描画する手順アニメ
- パスの全長 L を取得(
getTotalLength()) stroke-dasharray="L"で破線を 1 セットstroke-dashoffset="L"で完全に隠す- dashoffset を 0 にアニメすると、線が現れていく
線形グラデーション
<defs>
<linearGradient id="g1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="orange" />
<stop offset="50%" stop-color="red" />
<stop offset="100%" stop-color="purple" />
</linearGradient>
</defs>
<rect width="200" height="60" fill="url(#g1)" />
属性
- x1 / y1 / x2 / y2: 開始・終了点(既定 0,0 → 100%,0 = 横方向)
- gradientUnits:
objectBoundingBox(既定)/userSpaceOnUse - spreadMethod: pad(既定)/ reflect / repeat
- gradientTransform: 回転・スケール
放射状グラデーション
<defs>
<radialGradient id="g2" cx="50%" cy="50%" r="50%">
<stop offset="0%" stop-color="white" />
<stop offset="100%" stop-color="black" />
</radialGradient>
</defs>
<circle cx="100" cy="100" r="80" fill="url(#g2)" />
放射の中心をずらす
<radialGradient id="g3"
cx="50%" cy="50%" r="50%"
fx="30%" fy="30%">
<!-- ハイライトの中心が左上に -->
</radialGradient>
stop の opacity
<stop offset="0%" stop-color="black" stop-opacity="0" />
<stop offset="100%" stop-color="black" stop-opacity="1" />
パターン(タイル)
<defs>
<pattern id="dots" x="0" y="0" width="20" height="20"
patternUnits="userSpaceOnUse">
<circle cx="10" cy="10" r="2" fill="orange" />
</pattern>
</defs>
<rect width="200" height="200" fill="url(#dots)" />
主な使い方
- 背景の点描・縞・市松
- グラフのハッチング
- テクスチャ表現
マーカー(矢印など)
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="10" refY="5"
markerWidth="6" markerHeight="6" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="black" />
</marker>
</defs>
<line x1="10" y1="50" x2="100" y2="50"
stroke="black" stroke-width="2"
marker-end="url(#arrow)" />
- marker-start / marker-mid / marker-end
- orient="auto" で進行方向に回転
clipPath(切り抜き)
<defs>
<clipPath id="circle-clip">
<circle cx="100" cy="100" r="80" />
</clipPath>
</defs>
<image href="photo.jpg" width="200" height="200"
clip-path="url(#circle-clip)" />
クリップは0/1 のはっきりした切り抜き。エッジは硬い。
mask(透明度ベースの切り抜き)
<defs>
<mask id="fade">
<linearGradient id="g" x2="100%">
<stop offset="0%" stop-color="white"/>
<stop offset="100%" stop-color="black"/>
</linearGradient>
<rect width="100%" height="100%" fill="url(#g)"/>
</mask>
</defs>
<image href="photo.jpg" width="400" height="200" mask="url(#fade)" />
mask は明度(白=見える、黒=透明)でフェード可能。
filter(フィルタ)
ぼかし・影・色変換などのエフェクトを適用。
ぼかし
<defs>
<filter id="blur">
<feGaussianBlur stdDeviation="3" />
</filter>
</defs>
<rect filter="url(#blur)" ... />
ドロップシャドウ
<defs>
<filter id="shadow" x="-50%" y="-50%" width="200%" height="200%">
<feDropShadow dx="2" dy="2" stdDeviation="3" flood-opacity="0.3" />
</filter>
</defs>
<rect filter="url(#shadow)" ... />
色変換(feColorMatrix)
<filter id="grayscale">
<feColorMatrix type="matrix"
values="0.33 0.33 0.33 0 0
0.33 0.33 0.33 0 0
0.33 0.33 0.33 0 0
0 0 0 1 0"/>
</filter>
ネオン風(合成)
<filter id="neon">
<feGaussianBlur stdDeviation="4" result="blur" />
<feMerge>
<feMergeNode in="blur" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
filter のプリミティブ
- feGaussianBlur — ぼかし
- feOffset — 移動(影に使う)
- feFlood — 単色塗り潰し
- feComposite — 合成(in / out / atop / xor)
- feMerge — 重ね合わせ
- feColorMatrix — 色変換
- feTurbulence — ノイズ生成
- feDisplacementMap — 歪み
- feMorphology — 太らせ / 細らせ
- feDropShadow — 影(短縮形)
blend mode
図形同士の混合モード:
<rect ... style="mix-blend-mode: multiply" />
SVG の feBlend もあるが、CSS で書ける場合は CSS の方が楽。
currentColor を活用したアイコン色変え
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor"
stroke-width="2" stroke-linecap="round">
<path d="M3 12h18M3 6h18M3 18h18" />
</svg>
<style>
.menu-icon { color: #333; }
.menu-icon:hover { color: orange; }
</style>
linear-gradient を CSS で使う
SVG 内のグラデは複雑だが、img 表示なら CSS の background-image でも代替可能(DOM 要素の場合)。
SVG の中で使うなら <linearGradient> が必要。
失敗パターン
| 症状 | 対処 |
|---|---|
| グラデーションが見えない | id 参照ミス / objectBoundingBox の範囲 |
| filter で要素が切れる | filter の x/y/width/height を広げる |
| マスクが効かない | 白=見える、黒=透明(明度ベース) |
| 大きくすると線が太くなる | vector-effect="non-scaling-stroke" |
| 影が重い | filter は GPU 必須・サイズ大きいと重い |
パフォーマンス
- filter は重い。アニメに乗せると注意
- 大きすぎる stdDeviation はモバイルで負荷
- 大量の要素 + filter は避ける
- 影なら CSS の
filter: drop-shadow()でも代用可
グラデは defs に
グラデーションやフィルタは <defs> に置いて参照するのが流儀。
SVG をコンポーネント化するときも繰り返さずに済む。