塗り・線・グラデ・フィルタ

fill / stroke の細かい属性、線形 / 放射グラデ、パターン、フィルタ(blur / shadow / 色変換)、 clipPath / mask まで。

fill の指定

fill-rule

path に穴がある時、どこを「内側」とみなすか:

stroke の細かい属性

属性
stroke色 / url / none / currentColor
stroke-width太さ(数値)
stroke-opacity0〜1
stroke-linecapbutt / round / square
stroke-linejoinmiter / round / bevel / arcs(SVG 2)
stroke-miterlimitmiter の制限(既定 4)
stroke-dasharray破線パターン
stroke-dashoffset破線の開始位置
vector-effectnon-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 種パターン繰り返し -->

パスを描画する手順アニメ

  1. パスの全長 L を取得(getTotalLength()
  2. stroke-dasharray="L" で破線を 1 セット
  3. stroke-dashoffset="L" で完全に隠す
  4. 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)" />

属性

放射状グラデーション

<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)" />

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 のプリミティブ

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 必須・サイズ大きいと重い

パフォーマンス

グラデは defs に

グラデーションやフィルタは <defs> に置いて参照するのが流儀。 SVG をコンポーネント化するときも繰り返さずに済む。