Beyond Horizontal: Rotated and Vertical Text
SVG text is designed for decorative layouts, allowing you to position individual characters exactly where you want them. We showed in the book how you can shift individual characters in the x and y dimensions, with attributes on the containing element.
The final option for character positioning is the rotate
attribute, allowing you to set the angle of those characters.
Like x
, y
, dx
, and dy
, the rotate
attribute takes a list of values which are assigned, one-by-one, to the characters in the text content. The last value in the list affects all remaining characters in the current element—but, unlike with the positioning attributes, the rotation doesn’t persist for characters after the element’s end tag.
The values in rotate
are measured in degrees, but are given as numbers without units. Positive numbers are clockwise rotation, negative numbers are counter-clockwise.
Tip
Each rotation value is absolute, relative to normal layout, regardless of the previous value.
Each character is rotated relative to its own origin, rather than around the center of the glyph: this is normally the point at the “start” side of the baseline of the text. The rotations are applied after the rest of layout, and spacing of letters isn’t adjusted to fit. These details mean that rotate
is best used in combination with exact character placement with the other positioning attributes—don’t expect the browser to automatically create typographically-pleasing results with rotated characters.
To create more elegant rotated text, you can use <textPath>
(which we discuss in the book and in the “Perfecting Paths for <textPath>” article) to curve or angle a continuous line of text.
For vertical or sideways text, the writing-mode
property is a better option—although current browser implementations are not guaranteed to result in perfect typography, either.
Nonetheless, rotate
can be very effective at creating layouts that convey a sense of complete disorder, as done in Example 7-X2 (with the results in Figure 7-X2) to visualize a screaming voice falling out of control. In this case, we’re taking a vertical line of text and rotating each character by 15° more than the character before it, so that the letters flip around a full turn by the time they reach the bottom.
Example 7-X2. Using rotate
to alter the angle of individual characters
<svg
xmlns=
"http://www.w3.org/2000/svg"
xml:lang=
"en"
viewBox=
"0 0 200 500"
>
<title
>
Scream—Comic Book text
</title>
<style
>
@font-face
{
font-family
:
'SequentialistBB'
;
src
:
url
(
'fonts/SequentialistBB.woff2'
)
format
(
'woff2'
)
,
url
(
'fonts/SequentialistBB.woff'
)
format
(
'woff'
)
;
font-style
:
normal
;
font-weight
:
400
;
}
text
{
font-family
:
SequentialistBB
,
Papyrus
-
condensed
,
Impact
,
sans-serif
-
condensed
,
sans-serif
;
font-stretch
:
condensed
;
writing-mode
:
tb
;
/* SVG 1 syntax */
glyph-orientation-vertical
:
0
;
writing-mode
:
vertical
-
rl
;
/* CSS3 syntax */
text
-
orientation
:
upright
;
font-size
:
28px
;
}
tspan
{
font-size
:
75%
;
}
path
{
fill
:
#fff
;
stroke
:
#000
;
stroke-width
:
2
;
}
</style>
<path
d=
"M175,495 L140,465 C30,500 40,400 30,200 S70,10 100,10 S170,0 170,200 S170,400 150,450 Z"
/>
<text
x=
"100"
y=
"12"
rotate=
"0 15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 240 255 270 285 300 315 330 345 360"
textLength=
"450"
>
AAAaaaa
<tspan
>
aaaa
<tspan
>
aaaa
<tspan
>
aahhh!
</tspan >
!
</tspan>
!
</tspan>
!
</text>
</svg>
-
The
@font-face
rule is the same as previous examples in the book, as are the font styles designed to ensure that a similarly-proportioned fallback font will be used if the web font doesn’t load. -
The vertical layout is defined with the
writing-mode
and orientation properties: first, with the old SVG 1 syntax, and then with the new CSS3 syntax. -
As part of the “falling” layout, the text will get progressively smaller, using nested
<tspan>
elements, each set to afont-size
that is 75% of its parent’s size. -
The remaining aspects of the layout are defined by attributes on the
<text>
element itself: therotate
attribute lists different angles for each character, while thetextLength
attribute sets the overall length of the text to fit within the speech-bubble path. -
The nested
<tspan>
elements break up the stream of letters, with the final exclamation marks breaking out of the nested layers—and therefore each being larger than the last, back to the originalfont-size
.
We’ve mentioned vertical text before, but haven’t discussed it in full. It is only recently getting to the point of good browser support. Results are still somewhat buggy and inconsistent in web browsers (at the time of writing). However, it can be used for decorative effects like this where you’re not too worried about exact layout and perfect typography.
There are two syntaxes which can be combined to get almost-complete browser support for vertical writing modes:
- SVG 1.1 vertical text
-
-
uses
writing-mode
property with valuetb
to create vertical (top-to-bottom) lines of text; -
uses
glyph-orientation-vertical
property to set the type of vertical text layout, set to one of these values:-
0
for always upright (un-rotated) characters, stacked one under the other, -
90
to have the entire line rotated sideways, 90° clockwise, -
auto
(the default) to have sideways text for normally-horizontal scripts, but upright characters for scripts (like Chinese and Japanese) for which this is a standard writing style;
-
-
is fully supported in WebKit and Blink; Internet Explorer & Edge support
writing-mode
but not glyph orientation control; older Firefox had no support, but the latest Firefox versions now supportwriting-mode: tb
as a synonym for CSS 3 writing modes.
-
- CSS 3 vertical text
-
-
uses
writing-mode
property to set vertical text and line-wrapping direction, using one of these values:-
vertical-rl
for vertical text that wraps so that the first line of a paragraph is on the right (this is standard for Japanese and Chinese vertical text), -
vertical-lr
for vertical text that wraps so that the first line of a paragraph is on the left;
-
-
uses
text-orientation
property to set the type of vertical text:-
mixed
(the default, and the same asglyph-orientation-vertical: auto
), -
upright
for un-rotated characters, -
sideways
for sideways text rotated clockwise;
-
-
is currently (mid-2017) only supported in Firefox and Chrome/Blink, but is expected to be adopted everwhere eventually.
-
Example 7-X2 uses both syntaxes, relying on the CSS parser to let the new values override the old in supporting browsers. The double declarations provide full support for Blink, WebKit, and Firefox versions from 2016 and later, and partial support in IE and Edge.
Warning
In IE and Edge, the text will be laid out sideways before rotate
is applied, so each letter will be rotated an additional 90°.
Sideways text takes up a lot less vertical space than upright vertical text. And even among browsers that support upright vertical text, there is a lot of variation in how they space out the letters. The Sequentialist BB web font, like most fonts for normally-horizontal scripts, doesn’t include suggested vertical spacing in the font data.
To make sure the text fits the speech bubble in all these cases, and also with fallback fonts, we’ve used another new attribute: textLength
. The textLength
defines the exact total length that the text should cover. The browser then adjusts the spacing between characters to make it fit.
textLength
is a regular XML attribute, not a style property that can be set in CSS. It’s value is always a number, representing a distance in SVG user units (px units).
Warning
Browsers are all a little inconsistent about how they handle textLength
values when there are <tspan>
elements nested inside <text>
elements. Test carefully, and don’t use the attribute if you don’t have to.
The textLength
value means that we don’t have to worry about changing the text-anchor
to have a better fallback experience: we know exactly where the start, middle, and end of the text will be positioned because it will always have the same total length. But for other cases, it’s worth repeating: for vertical text, text-anchor
defines the vertical alignment, relative to the y
position of the text chunk.