jvinhit//lab

Search posts

Type to search across journal entries.

navigate open esc close

SVG from Zero to Senior · Part 4 — Text & textPath

SVG text is real, selectable, accessible text living in the coordinate system. Master baseline positioning, text-anchor, multi-line and styled tspans, and the showpiece — flowing a label along any curve with textPath. With a live lab.

6 MIN READ

Most people reach for HTML when they need words, and SVG when they need shapes. {Đa số dùng HTML khi cần chữ, dùng SVG khi cần hình.} But SVG text is its own superpower: it lives in the coordinate system, scales perfectly, can be filled with gradients, clipped, animated — and crucially, it stays real, selectable, accessible text, not a picture of text. {Nhưng text SVG là siêu năng lực riêng: nó sống trong hệ toạ độ, scale hoàn hảo, có thể tô gradient, clip, animate — và quan trọng, nó vẫn là chữ thật, chọn được, truy cập được, không phải ảnh chụp chữ.}

Drag the controls — move the baseline, change the anchor, bend the curve — then read the rules. {Kéo các control — dịch baseline, đổi anchor, uốn đường cong — rồi mới đọc luật.}

Open the full demo {Mở demo đầy đủ}: /tools/svg-text-demo/.

The baseline gotcha {Cái bẫy baseline}

The number one surprise: in SVG, y is the baseline, not the top of the text. {Bất ngờ số một: trong SVG, ybaseline, không phải đỉnh chữ.}

<text x="20" y="40" font-size="28">Hello SVG</text>

That text sits above y=40, with descenders (the tails of g, y, p) dropping below it. {Chữ đó nằm trên y=40, với phần descender (đuôi g, y, p) thả xuống dưới.} If your text seems to be clipped at the top of the viewBox, you set y too small. {Nếu chữ bị cắt ở đỉnh viewBox, con đặt y quá nhỏ.} Use dominant-baseline="middle" (or central) when you want true vertical centring, e.g. labels inside a circle. {Dùng dominant-baseline="middle" (hoặc central) khi muốn canh giữa dọc thật sự, ví dụ nhãn trong vòng tròn.}

text-anchor — horizontal alignment {text-anchor — canh ngang}

text-anchor decides what the x point means: {text-anchor quyết định điểm x có nghĩa gì:}

  • start (default) — x is the left edge (in LTR). {x là mép trái (với văn bản trái-sang-phải).}
  • middlex is the centre. The go-to for centred labels. {x là tâm. Lựa chọn cho nhãn canh giữa.}
  • endx is the right edge. {x là mép phải.}
<text x="150" y="80" text-anchor="middle">Centred</text>

This is the tool for labels in charts and badges — anchor to a fixed point and the text grows symmetrically. {Đây là công cụ cho nhãn trong biểu đồ và huy hiệu — neo vào một điểm cố định và chữ nở đối xứng.}

tspan — spans, offsets, and fake line breaks {tspan — span, offset, và xuống dòng giả}

SVG text does not wrap automatically and ignores \n. {Text SVG không tự xuống dòng và bỏ qua \n.} To style part of a string or make multiple lines, use <tspan>: {Để style một phần chuỗi hoặc tạo nhiều dòng, dùng <tspan>:}

<text x="20" y="40" font-size="24">
  Total:
  <tspan fill="#c8ff00" font-weight="600">$1,240</tspan>
</text>

<!-- multi-line: each tspan resets x and nudges y with dy -->
<text x="20" y="40">
  <tspan x="20" dy="0">Line one</tspan>
  <tspan x="20" dy="1.2em">Line two</tspan>
</text>

dx/dy shift relative to the previous glyph — perfect for superscripts, kerning tweaks, and the line-break pattern above. {dx/dy dịch tương đối so với glyph trước — hoàn hảo cho chỉ số trên, tinh chỉnh kerning, và mẫu xuống dòng ở trên.} If you need real paragraph wrapping, that is a job for HTML inside <foreignObject> — but use it sparingly. {Nếu cần wrap đoạn văn thật, đó là việc của HTML trong <foreignObject> — nhưng dùng tiết kiệm.}

textPath — the showpiece {textPath — món đinh}

Here is the effect you cannot do in plain CSS: text that follows a curve. {Đây là hiệu ứng con không làm được bằng CSS thuần: chữ đi theo đường cong.} Define a path, then reference it from a <textPath>: {Định nghĩa một path, rồi tham chiếu từ <textPath>:}

<defs>
  <path id="curve" d="M 20 110 Q 150 40 280 110" />
</defs>
<text font-size="18" fill="#60a5fa">
  <textPath href="#curve" startOffset="0%">
    SVG TEXT ON A CURVE •
  </textPath>
</text>
  • The text rides along the path’s length, each glyph rotated to the local tangent. {Chữ chạy dọc theo chiều dài path, mỗi glyph xoay theo tiếp tuyến cục bộ.}
  • startOffset (a length or %) slides where the text begins — animate it and the text scrolls along the path. {startOffset (độ dài hoặc %) dời chỗ chữ bắt đầu — animate nó và chữ trượt dọc path.}
  • The referenced path is not drawn unless you also render it; in production give it stroke="none". {Path được tham chiếu không được vẽ trừ khi con render nó; trong production cho nó stroke="none".}

This powers circular badges (”★ OFFICIAL ★ SELECTION ★”), ribbon labels, and curved chart annotations. {Cái này tạo nên huy hiệu tròn, nhãn ruy băng, và chú thích biểu đồ cong.} Use the old xlink:href only if you must support ancient browsers; modern SVG uses plain href. {Chỉ dùng xlink:href cũ nếu phải hỗ trợ trình duyệt cổ; SVG hiện đại dùng href thường.}

Fonts and the portability trap {Font và cái bẫy chuyển giao}

SVG text uses whatever font is available at render time, exactly like CSS. {Text SVG dùng font nào có sẵn lúc render, y như CSS.} If you ship an SVG that references “Brand Sans” and the viewer doesn’t have it, they get a fallback. {Nếu con ship SVG tham chiếu “Brand Sans” mà người xem không có, họ nhận font dự phòng.} For pixel-perfect logos that must look identical everywhere, designers convert text to paths (outlines) on export — at the cost of losing selectability and accessibility. {Cho logo cần giống hệt mọi nơi, designer chuyển text thành path (outline) khi export — đánh đổi mất khả năng chọn và truy cập.} Senior call: keep text as text for UI and content; outline it only for fixed brand artwork. {Quyết định senior: giữ text là text cho UI và nội dung; chỉ outline cho artwork thương hiệu cố định.}

The master’s warnings {Lời cảnh báo của sư phụ}

  • y is the baseline. Text disappearing off the top? Increase y. {y là baseline. Chữ biến mất trên đỉnh? Tăng y.}
  • No auto-wrap. Long strings overflow the viewBox silently. Plan line breaks with <tspan>. {Không tự wrap. Chuỗi dài tràn viewBox lặng lẽ. Lên kế hoạch xuống dòng bằng <tspan>.}
  • textPath needs a real path id in the same document. A broken href renders nothing, no error. {textPath cần id path thật trong cùng tài liệu. href hỏng thì không render gì, không báo lỗi.}

Practice, or it didn’t happen {Luyện tập, không thì coi như chưa học}

  1. Centred badge label {Nhãn huy hiệu canh giữa}: text with text-anchor="middle" and dominant-baseline="central" dead-centre in a circle. {text với text-anchor="middle"dominant-baseline="central" ngay giữa vòng tròn.}
  2. Price line {Dòng giá}: one <text> with a muted label and a bright <tspan> for the number. {một <text> với nhãn mờ và một <tspan> sáng cho con số.}
  3. Circular stamp {Con dấu tròn}: a circle path + <textPath> so a slogan wraps around the top. Animate startOffset to rotate it. {path tròn + <textPath> để khẩu hiệu chạy vòng trên. Animate startOffset để xoay.}

What’s next {Phần tiếp theo}

You can now draw, paint, and letter. {Giờ con vẽ, sơn, và viết chữ được.} But everything so far has been static and flat in one coordinate system. {Nhưng mọi thứ tới giờ vẫn tĩnh và phẳng trong một hệ toạ độ.} In Part 5 we learn to move and reuse: the transform attribute (translate/scale/rotate/skew), why order matters, grouping with <g>, and the mind-bending power of nested coordinate systems with inner <svg> elements. {Ở Phần 5 ta học di chuyển và tái dùng: thuộc tính transform (translate/scale/rotate/skew), vì sao thứ tự quan trọng, gom nhóm bằng <g>, và sức mạnh xoắn não của hệ toạ độ lồng nhau với <svg> bên trong.}