Chapter 11: SVG text and tspan
SVG text and tspan elements in great detail. These let you put real, selectable, stylable, searchable text inside SVG — something you cannot do with normal images (PNG/JPG).
I’m going to explain it like we’re sitting together with the code open — slowly, clearly, with many examples you can copy-paste right now.
Why use SVG <text> at all?
- Text stays sharp at any zoom level (vector!)
- You can style it with CSS (color, font, size, hover effects, dark mode…)
- Search engines can read it (great for SEO — logos with text, diagrams)
- Users can select & copy the text
- You can animate letters individually, make curved text, multi-line, different styles in one sentence…
- Perfect for: logos, icons with labels, data labels on charts, buttons, maps, infographics
The basic <text> element
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<svg width="500" height="180" style="border:1px solid #eee; background:#f9f9f9;"> <text x="250" y="100" font-size="60" fill="#673AB7" text-anchor="middle" font-family="Arial, sans-serif"> Hello SVG! </text> </svg> |
Important attributes on <text>:
| Attribute | Meaning | Common values | Default | Very useful? |
|---|---|---|---|---|
| x | Horizontal position (anchor point) | number, %, etc. | 0 | ★★★★★ |
| y | Vertical position (baseline) | number, %, etc. | — | ★★★★★ |
| font-size | Size of text | 16px, 3em, 48, etc. | (browser) | ★★★★★ |
| fill | Color of text | #FF5722, purple, currentColor | black | ★★★★★ |
| text-anchor | How text aligns to x position | start / middle / end | start | ★★★★☆ |
| font-family | Font stack | “Roboto”, “Arial, sans-serif” | browser | ★★★★☆ |
| font-weight | bold, normal, 700… | normal, bold, 400, 700 | normal | ★★★☆☆ |
| dominant-baseline | Vertical alignment of text | auto, middle, central, hanging… | auto | ★★★☆☆ |
Important note about y coordinate In SVG, the y value is the baseline of the text (like the line letters sit on), not the top or center. That’s why many people add dominant-baseline=”middle” or central when they want true vertical centering.
Example 2 – Centered text with better vertical alignment
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<svg width="400" height="200"> <rect x="40" y="40" width="320" height="120" fill="#2196F3" rx="12"/> <text x="200" y="100" font-size="48" fill="white" text-anchor="middle" dominant-baseline="middle" font-family="Helvetica, Arial, sans-serif" font-weight="bold"> CENTERED </text> </svg> |
Now — the real power: <tspan>
<tspan> = text span — lets you change style, position, rotation… inside the same line of text without breaking flow.
You put <tspan> inside a <text> (or even nested inside another <tspan>).
Common use cases:
- Different colors in one sentence
- Bigger/smaller words
- Superscripts / subscripts
- Shift some letters up/down
- Rotate individual characters
Example 3 – Using <tspan> for mixed styles
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<svg width="520" height="140"> <text x="20" y="80" font-size="52" fill="#333" font-family="Arial"> I love <tspan fill="#E91E63" font-weight="bold">SVG</tspan> because it's <tspan fill="#2196F3" font-style="italic">vector</tspan>! </text> </svg> |
Example 4 – Position shifts with dx/dy (very useful for icons + label)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<svg width="360" height="140"> <text x="40" y="90" font-size="64" fill="#FF5722" text-anchor="start"> 85 <tspan font-size="36" baseline-shift="super" dy="-8">%</tspan> <tspan dx="20" fill="#4CAF50">Great!</tspan> </text> </svg> |
- dx = shift horizontally from previous position
- dy = shift vertically from previous position
- baseline-shift=”super” = common for superscript (alternative to dy)
Example 5 – Character-by-character rotation (fun effect!)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<svg width="420" height="220"> <text x="210" y="110" font-size="72" fill="#673AB7" text-anchor="middle"> <tspan rotate="0">W</tspan> <tspan rotate="15">A</tspan> <tspan rotate="30">V</tspan> <tspan rotate="45">Y</tspan> <tspan rotate="60">!</tspan> </text> </svg> |
Bonus: Curved text with <textPath>
(Advanced but very popular — needs a <path> or <circle> first)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<svg width="400" height="300"> <defs> <path id="curve" d="M 50 200 Q 200 50, 350 200" /> </defs> <text font-size="48" fill="#FF9800" font-weight="bold"> <textPath href="#curve" startOffset="50%" text-anchor="middle"> Follow the curve! </textPath> </text> <!-- Optional: show the path faintly --> <use href="#curve" stroke="#ccc" stroke-width="2" fill="none"/> </svg> |
Here are some visual examples of what <text> with <tspan> and <textPath> can achieve (mixed styles, superscript, curved text, rotated letters):
(Imagine seeing here: one image showing colorful mixed-style text, one showing percentage with superscript, one showing text curved along an arc, one showing individual letter rotation.)
Quick Cheat Sheet – <text> & <tspan> vs HTML <p>
| Feature | SVG <text>/<tspan> | HTML <p>/<span> |
|---|---|---|
| Resolution independent | Yes | Yes (but depends on font) |
| Can curve / follow path | Yes (<textPath>) | No (needs complex CSS/SVG) |
| Per-character rotation | Yes | Hard / no native support |
| Part of vector graphic | Yes — scales perfectly | No — bitmap when exported |
| Selectable & copyable | Yes | Yes |
| Easy multi-line | Manual (multiple <text> or <tspan> dy) | Automatic |
| Best for | Icons, charts, logos, diagrams | Long paragraphs, articles |
Common beginner mistakes
- Forgetting to set fill → text invisible (no default color like black in some browsers)
- Using y as top edge → text sits too low (use dominant-baseline=”hanging” or adjust y)
- Nesting <tspan> too deeply without reason → harder to maintain
- No font-family → falls back to Times New Roman (ugly in many cases)
Mini practice tasks
- Make a big purple “SALE” text where “SALE” is bold & red, and “20% OFF” is smaller & green below it
- Create a circular badge with text curved around the top half
- Write “SVG is AWESOME” where each letter of “AWESOME” is rotated 10° more than the previous one
Paste your code here if you want feedback — I’ll review it like we’re pair-programming 😄
Any part still confusing? The baseline? tspan positioning? textPath? Curved text? Just point and ask — we’ll redraw examples until it’s crystal clear! 🚀
