SVG テキスト

text / tspan / textPath。フォント、整列、文字単位の装飾、パスに沿わせる、フィットする方法まで。

text 要素

<text x="50" y="50" font-family="sans-serif" font-size="20">
  Hello SVG
</text>

主要な属性

属性意味
font-familyフォント
font-sizeサイズ
font-weight太さ
font-styleitalic 等
text-anchorstart / middle / end(横方向の整列)
dominant-baselinemiddle / hanging / alphabetic(縦方向)
letter-spacing字間
word-spacing語間
fill文字色
stroke輪郭
writing-modevertical-rl / horizontal-tb

横方向の整列(text-anchor)

text-anchor:
start    Hello                ← x が左端
middle      Hello             ← x が中心
end           Hello           ← x が右端
      
<text x="100" y="50" text-anchor="middle" font-size="20">
  Centered
</text>

縦方向の整列(dominant-baseline)

tspan(部分装飾 / 改行)

<text x="50" y="50" font-size="16">
  Hello
  <tspan fill="orange" font-weight="bold">SVG</tspan>
  World
</text>

tspan で改行

SVG 1 は自動折り返しなし。tspan + x + dy で手動改行:

<text x="0" y="20">
  <tspan x="0" dy="0">1 行目</tspan>
  <tspan x="0" dy="1.2em">2 行目</tspan>
  <tspan x="0" dy="1.2em">3 行目</tspan>
</text>

個別の x / y

<!-- 文字ごとに位置指定(タイポグラフィ表現) -->
<text>
  <tspan x="10" y="20">H</tspan>
  <tspan x="30" y="40">i</tspan>
</text>

textPath(パスに沿った文字)

<defs>
  <path id="curve" d="M 10 80 Q 100 10 190 80" fill="none" />
</defs>

<text font-size="16">
  <textPath href="#curve">
    曲線に沿った文字列
  </textPath>
</text>

属性

SVG 2 の x="..." のリスト

text や tspan に複数の x を渡すと各文字に適用される(Animated typography で多用):

<text x="10 20 30 40 50" y="50">Hello</text>
<!-- H=10, e=20, l=30, l=40, o=50 -->

Web フォント

<style>
  @import url("https://fonts.googleapis.com/css2?family=Inter&display=swap");
  text { font-family: Inter, system-ui, sans-serif; }
</style>

外部 SVG ファイルではフォントがロードされないことがある(→ ファイルに埋め込むか、ブラウザフォントに頼る)。

テキスト → パス化

ロゴでフォントを誰の環境でも同じに見せたいなら、Illustrator / Inkscape でパスにアウトライン化。 編集はできなくなるが、フォント環境に依存しない。

整列を厳密に(dominant-baseline と組合せ)

<circle cx="50" cy="50" r="40" />
<text x="50" y="50"
  text-anchor="middle"
  dominant-baseline="central"
  font-size="20">
  Hi
</text>

円の真ん中に文字を置く定番セット。

foreignObject(HTML 埋め込み)

SVG の中にHTML を直接埋め込める。複雑なレイアウト / 改行付きテキストで便利。

<foreignObject x="10" y="10" width="200" height="100">
  <div xmlns="http://www.w3.org/1999/xhtml" style="font-size: 14px">
    HTML が入る。
    自動的に折り返す段落も普通に書ける。
  </div>
</foreignObject>

注意

テキストの長さを揃える

<text x="10" y="20" textLength="180" lengthAdjust="spacingAndGlyphs">
  Stretched to 180
</text>

writing-mode(縦書き)

<text writing-mode="vertical-rl" font-size="20">縦書きテキスト</text>

CSS で変える

svg text { font-family: 'Inter', sans-serif; }
svg .heading { font-size: 32px; font-weight: 700; }

テキストの上にエフェクト

フチ

<text stroke="black" stroke-width="3" paint-order="stroke" fill="white">
  Outlined
</text>

paint-orderstroke にすると、線が下、塗りが上で重なる。

<text style="filter: drop-shadow(2px 2px 2px rgba(0,0,0,.3))">
  Shadow
</text>

グラデ文字

<defs>
  <linearGradient id="g" x2="100%">
    <stop offset="0%" stop-color="orange" />
    <stop offset="100%" stop-color="purple" />
  </linearGradient>
</defs>
<text fill="url(#g)" font-size="48">Gradient</text>

失敗パターン

症状対処
自動改行されないSVG 1 の仕様。tspan で手動 / foreignObject
整列がずれるtext-anchor + dominant-baseline をセットで
外部 SVG でフォントが違うシステムフォント / アウトライン化
テキストパスがズレるstartOffset / 文字数とパス長
選択できないpointer-events / user-select 設定
テキスト派 vs パス派

編集 / 翻訳 / 検索が要るならテキストのまま。同じ見た目を保証したいならパス化。 多言語対応の SVG はテキスト派でないと辛い。