Notes for a presentation by Amelia Bellamy-Royds
SVG Summit, 15 February 2017
I've set up a CodePen as a scratchpad for the live-coding bits. Don't expect anything there to stay there long; fork the pen if you want to save the code & look at it later.
- Text in SVG
- Actual text characters included in the markup file, as the text content of DOM nodes
- Defined by the
<text>
element - Modified by
<tspan>
and/or<textPath>
child elements - Shapes of letters from a font
- Font selection via CSS styles, including
@font-face
web fonts - Color & effects painted like SVG shapes (
fill
,stroke
,filter
) - Layout via SVG element attributes, SVG-specific CSS styles, and some cross-over styles
Examples:
- Live code: quick & dirty text & tspan
- Wood Lily, labelled diagram with hover effects
- Characters are not glyphs, showing fancy filters on text in different fonts
- SVG graphics shaped like text, but encoded as
<path>
elements (such as created by "convert text to path" options): this is an image of text, isn't affected by text layout/styles in the browser, and must have alternative text.- For inline SVG, alternative could be transparent
<text>
over top of the paths (best), or alt text from a child<title>
element or anaria-label
attribute (good for screen-readers & search engines, but no keyboard selection). - For SVG as an image, use
alt
attribute, or use sibling HTML text that is either shifted off-screen or made transparent (best).
- For inline SVG, alternative could be transparent
- A replacement for CSS and HTML text layout: there is no browser support yet for auto-wrapping text in SVG, let alone features like bulleted lists or padding & borders around spans.
- Can use
<foreignObject>
to embed HTML text blocks in SVG (but no support in Internet Explorer).
- Can use
Example:
- Instead of HTML text:
- Integrated in an SVG drawing's coordinate system
- Scales with
viewBox
- Simple, well-supported gradient/pattern-filled text, and text strokes
- Good browser support for transforms (as attributes), clip-paths, masks & filters
- Instead of images of text or text as paths:
- Real text is easy to edit
- Real text is screen-reader accessible
- Real text can be selected, copied, translated
- Real text can be found by in-page search, and by search engines
- SVG text is infinitely scalable by screen magnifiers & can be styled with
currentColor
to match high contrast screens (although both of these also apply to text converted to SVG paths)
Examples:
- None of the accessibility benefits (relative to SVG paths) come through if SVG is used as an image (
<img>
orbackground-image
): may as well convert to paths & use HTML for accessible text. - Exact layout & appearance depend on fonts: you can use web fonts, but must be willing to accept fallbacks.
- Creating custom glyph shapes is difficult, with poor browser support. Custom artistic text must still be drawn with
<path>
(but you can overlay transparent real text to get accessibility & interaction).
That's a big question, let's break it down:
- You always need a
<text>
:<tspan>
and<textPath>
don't render on their own. <tspan>
inside<text>
allows you to switch styles and/or re-set layout.<textPath>
positions its text along a<path>
referenced byxlink:href
: curved text, easy angled text- When copying & pasting, and for accessibility, browsers treat each
<text>
as a paragraph,<tspan>
and<textPath>
are spans. - But beware: since they're treated as inline you can't
transform
a<tspan>
or<textPath>
(even if they are de-facto absolutely positioned). <a>
is also allowed inside<text>
: styles can be switched, but not SVG text layout.- Link Tip #1: SVG links aren't styled by default; be sure to add your own styles.
- Link Tip #2: Use
xlink:href
instead ofhref
for support in Safari & older Chrome/FF. - Link Tip #3: You can use a
target
attribute to open link in another tab, or another<iframe>
or<object>
in the current page. - Link Tip #4: You can use the
:target
pseudoclass to style elements when you click on a link, and link targets also activate SVG views and SVG/SMIL animation elements.
Examples:
- "Cool Yule" again: note diagonal text is a
<textPath>
- Oodles of
<tspan>
in the concrete layout of this Lewis Carroll poem <tspan>
inside<textPath>
inside<text>
- SVG text layout is not CSS text layout! CSS defines boxes & flows text inside. SVG defines anchor points and positions "chunks" of text around them.
- SVG 1.1 text does not wrap! You set the initial position, and text is laid out like a typewriter until you tell the browser to switch to a different position.
- Text positions are assigned to characters, not to elements, and can be absolute (
x
ory
) or relative (dx
ordy
). Each attribute takes a list of values, and inherits into nested elements. - An absolute position in the direction of text flow (
x
for horizontal text) creates an anchor point. - "Chunks" are a series of characters starting with the one that has an anchor assigned to it.
- You can have one anchor for the entire
<text>
, or an anchor for each character, or anything in between. - By default, the chunk is positioned so the baseline of the first character is at the anchor.
- Change the main alignment with
text-anchor
:start
,middle
, orend
; effect depends on text direction. - Beware: leading/trailing whitespace in a chunk is used in the alignment!
- Theoretically, you can change the cross alignment with
alignment-baseline
,dominant-baseline
, andbaseline-shift
: but browser support is a disaster. - Instead, use
dy
to shift text up and down relative to the anchor. (Ordx
for vertical text.) - Yes, you can do vertical text! But there are two syntaxes: SVG 1.1 vs CSS 3; currently need both for cross-browser support (and there are still bugs & limitations).
- Add a
rotate
attribute for even more control, but only recommended if you're absolutely positioning individual characters (or if you want an off-kilter effect).
Examples:
- Live coding:
x
,y
,dx
,dy
text-anchor
basicstext-anchor
advanced- Text baselines, in theory
- Vertical text comparison
- For
<textPath>
, the position is defined by the linked path: if there's no path, nothing is rendered. - The position is as if the
<path>
was re-drawn in the<text>
element's coordinate system. Transforms from the<path>
itself apply, but not from its ancestors. - Define the initial anchor point using a
startOffset
attribute; value can be a length or a percent of path length.- For text centered on a path, use
startOffset="50%"
andtext-anchor: middle
. - In theory, create a marquee effect by animating
startOffset
, but beware a bug in old Chrome and current WebKit.
- For text centered on a path, use
dx
, anddy
apply to text inside the<textPath>
, but:- cannot be set on the
<textPath>
itself, only on parent/child<text>
or<tspan>
; - are treated as offsets along the path or perpendicular to the path, instead of horizontal and vertical.
- cannot be set on the
x
andy
can also be set, but avoid because of cross-browser inconsistencies.- FYI: Right-to-left text on a path, and cursive script text on a path are browser support disasters!
Examples:
- Wavy Walrus & the Carpenter
<tspan>
inside<textPath>
inside<text>
, withdy
offsets- Working around negative startOffset bug with offscreen path sections
- Trying to use Arabic text on a path
-
Familiar CSS-for-text styles
- Usual CSS styles for selecting font (
font
,font-family
,font-size
,font-weight
, etc.) and@font-face
rules. text-decoration
(TIP: useoverline underline
for a border effect on all-caps text).- Theoretically,
letter-spacing
&word-spacing
(but no Firefox support). text-transform
in browsers (not officially required by SVG specs).- Note:
color
does not have a direct effect; usefill: currentColor
to inherit HTML color and/or to ensure your text will play well with High Contrast mode.
- Usual CSS styles for selecting font (
-
Familiar CSS-for-SVG styles
fill
andstroke
, including gradients and patternspaint-order
(in latest browsers except Edge)stroke-linejoin
,stroke-linecap
(though few fonts will have open paths in glyphs)stroke-dasharray
andstroke-dashoffset
(but no way to identify total path length or control default dash offset)filter
,clip-path
,mask
-
Direction and writing mode properties
direction
andunicode-bidi
for right-to-left text (with similar effect to HTML attributes).writing-mode
andtext-orientation
for vertical text (use CSS 3 syntax with fallback to SVG 1.1 syntax).
-
Whitespace control
white-space
, in theory (new in SVG 2); XMLxml:space
attribute from SVG 1.1 also poorly supported in web browsers.
Examples:
- Live coding
- Image-pattern fill, also showing overline/underline effect
- Gradient and pattern fill, showing how gradients continue across multiple
<tspan>
elements in the same<text>
-
Use HTML (embedded with an SVG
<foreignObject>
or absolutely positioned on top of the SVG) for:- Paragraphs of text
- Dynamic labels which may need to wrap, unless you're going to add JS code to calculate the wrapping points
contenteditable
or input elements- Custom image icons inline in text
- Tables or other complex formatting, especially if any text is dynamic
-
Use paths (with alt text) for:
- Logos or wordmarks where font is essential
- Distorted or custom glyph shapes not found in the font
- Stroke-drawing animation to create a hand-written effect
- Check out the new SVG 2 text spec
- Auto-wrapping text with a fixed max line length
- Pre-formatted multi-line text
- Text in a shape
- Easier to use text paths
- Lots of clarifications about other layout details
- Browsers are holding back on making any commitments to implement these new features (and as a side effect, have also dropped any plans to build a better SVG test suite): they need to know which issues are causing problems & which features you really want.
- Upvote/file Chrome/Blink bugs & feature requests here
- Upvote/file Firefox/Gecko bugs & feature requests here
- Upvote/file Safari/WebKit bugs & feature requests here
- For MS Edge: File bugs on existing features here, Submit & upvote feature requests via user voice
PS: You can find more examples from the SVG Text Layout book in its supplementary materials, or the text chapter & a few others from the SVG Colors, Patterns & Gradients book or Search my CodePen. The examples from the upcoming Using SVG book will be online soon.
More questions? Want some help amplifying that new bug report you just filed? Ping me on Twitter @AmeliasBrain.