Text in SVG
SVG treats a text element in much the same way that it treats graphical and shape elements. You position text with x and y coordinates and use fill and stroke options to color text the same way you would with a <circle> or <rect> element. However, SVG allows a surprising amount of control over how text appears (such as fonts, letter spacing, alignment), much like any good text layout program, but in addition offers the ability to internationalize your text message. Few other applications or computer languages permit this flexibility. This is because text in SVG remains character data even after it is rendered, so it is searchable and can be edited, even if it is a graphical element.
The <text> Element
In SVG, text is rendered with the <text> element. The simplest example of a <text> element is one that uses just x and y attributes to place it. Text is rendered by default with a black fill and no outline. Unlike other objects, this is usually fine for words. Example 310 shows this simple use of the <text> element.
Example 310
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="300" height="300"> <text x="85" y="124">Text in SVG</text> </svg>
This code results in the image shown in Figure 313.
The letters were placed in position with the <text> element, using its x and y attributes. Text is positioned (unlike the <rect> element) with its lower left corner at the coordinates specified in the x and y attributes.
The <text> element in Example 310 does not have any style attributes, so SVG gave it the default black fill and no outline.
FIGURE 313 The <text> element (TEXT01.SVG).
Characters and Glyphs
To understand text in SVG, it's useful to take a look at the difference between characters and glyphs. A character is a letter, number, or punctuation mark, such as the letter A. A glyph, on the other hand, is the way that particular character is rendered; for instance, A, A, A, and A are all versions of the capital letter A character. But they are displayed in different fonts, which means that they are all different glyphs. A character is the basic idea of a letter or number, and a glyph is the way it is rendered on screen or paper.
In SVG text, the <text> element is held as character data, which makes it accessible to searches and internationalization. You can control the way SVG renders text by choosing attributes, transforming it, specifying fills and strokes, and specifying fonts, font-size, and spacing.
In this book, we'll use the style attribute to specify many presentational text characteristics, such as font-family, font-style, and so on. Note that you don't need to put these in the style attribute; you can use them on their own. In other words:
<text x="50" y="100" font-family="arial" font-size="18">
and
<text x="50" y="100" style="font-family:arial; font-size:18">
are equivalent statements. This means you can write them with either the font name in quotes or the entire font family name in quotes, as in the above example.
SVG does not yet recognize (as of this writing) newlines and tabs, so the <text> element renders text in one line. If you want your text to be on more than one line, you can use either multiple <text> elements or the <tspan> element (which we describe later in this chapter) to break the text up. You would have to give each new <text> line new x and y coordinates, depending on how you wanted the lines to render. Example 311 shows multiple <text> elements displaying lines of poetry.
Example 311
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="300" height="300"> <text x="55" y="55">When I grow old with wandering</text> <text x="55" y="75">Through hollow lands and hilly lands</text> <text x="55" y="95">I will find out where she has gone</text> <text x="55" y="115">and kiss her lips and take her hand</text> <text x="55" y="135">and walk among long dappled grass</text> <text x="55" y="155">and pick til time and times are done</text> <text x="55" y="175">the silver apples of the moon,</text> <text x="55" y="195">the golden apples of the sun</text> </svg>
We changed the y attribute for each line of text to space the W.B. Yeats verse. Figure 314 shows how the SVG file will look on screen.
FIGURE 314 Multiple <text> elements to create a multiline text poem (POETRY.SVG).
Table 37 shows the <text> element and its attributes.
TABLE 37 <text> Element and Attributes
Element |
Attributes |
Description |
<text> |
x |
x coordinate for lower left corner of text string |
|
y |
y coordinate for lower left corner of text string |
|
dx |
Shifts along the x axis for characters in the <text> element that includes this attribute |
|
dy |
Shifts along the y axis for characters in the <text> element that includes this attribute. (Note: can be used for super- or subscript characters) |
|
rotate |
Rotation about the current text position. Can be used instead of the transform=rotate() attribute to rotate text |
|
textLength |
Author's computation of the length of the text string. Used to calculate adjustments when exact positioning is necessary |
|
lengthAdjust |
This attribute has two options"spacing" and "spacingAndGlyphs" The former (spacing) will adjust the spacing between glyphs but will not stretch or squeeze the glyphs themselves. spacingAndGlyphs (as the name states) will adjust both spacing between glyphs and glyph size. |
The dx and dy attributes shown in Table 37 are useful for shifting characters slightly, as with super- or subscript characters. Example 312 shows a <text> element with both dx and dy attributes applied:
Example 312
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="300" height="300"> <text x="55" y="105">Water is H</text> <text dx="110" dy="112">2</text> <text dx="120" dy="105">0</text> </svg>
We used the dx and dy attributes to render the subscript 2 in H2O properly. The dx attribute places a character horizontally, so we needed to put the 2 character just to the right of the H character, and the O character just to the right of the 2 character. The dy attribute places a character vertically, so the 2 character is placed at 112 instead of 105, and the O character is back at 105 to line up with the rest of the text. We needed to place the O character back at the y coordinate of 105, because the x and y positions of a <text> element will stay at the dx and dy positions unless specified otherwise.
You can also create super- and subscript characters by using the baseline-shift property, as we will see a bit later in this chapter, when we discuss text alignment.
The other text attributes (rotate, textLength, and lengthAdjust) will be investigated during the text layout part in this chapter.
The <tspan> Element
The <tspan> element adjusts text properties within a <text> element. An example of this would be if you wanted to render the following sentence in SVG: "This is an example of tspan." The sentence uses bold, italics, and a different font all in one sentence. The <tspan> elements can be embedded within a <text> element to handle all of the text-rendering needs within that sentence. Example 313 illustrates this.
Example 313
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="300" height="300"> <text x="55" y="105" style="font-family:times">This <tspan style="font-style:italic">is </tspan> <tspan style="font-style:normal">an </tspan> <tspan style="font-weight:bold">example </tspan> <tspan style="font-style:italic;font-weight:bold"> of </tspan> <tspan style="font-family:arial; font-style:normal; font-weight:normal">tspan.</tspan> </text> </svg>
The code shows multiple <tspan> elements used with different style properties to create the look of a sentence with bold and italic characters, as well as characters with a different font. Figure 315 displays the result of the code from Example 313 in a browser.
FIGURE 315 Multiple <tspan> elements create text with different properties within one <text> element.
The <tspan> element can also be used for multiline text. Just remember that <tspan> is always embedded within a <text> element!
All of the attributes listed in Table 37 that apply to the <text> element (x,y, dx,dy, rotate, textLength, and lengthAdjust) also apply to the <tspan> element, in much the same way as they are used in the <text> element.
The <tref> Element
The <tref> element references text that has been created in a <defs> element, either in the same or another SVG document. The <tref> element uses the "xlink:href="(uri)" attribute to reference text when it has been created elsewhere and given an id attribute. Example 314 shows a <text> element placed in a <defs> element and referenced later in the SVG document via the <tref> element.
Example 314
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="300" height="300"> <!-- define text--> <defs> <text id="referencedText" style="font-family:times; font-weight:bold">This is referenced text.</text> </defs> <!-- use tref to reference text defined and created elsewhere --> <text x="50" y="100"> <tref xlink:href="#referencedText"/> </text> </svg>
Like the <use> element, <tref> can reference text within the SVG file. The <text> element referenced has to contain an id attribute in order to be visible. <tref> cannot reference whole documents but can reference <text> elements defined within a different document.
Fonts and Layout
SVG has numerous attributes and values related to fonts and layout, so you are by no means relegated to the vanilla text style we've been using so far! You'll see that SVG can do just about anything that a good word processing or text layout application can do.
Fonts and Font Properties
Table 38 lists font properties available in SVG.
TABLE 38 Font Properties
Property |
Value |
Description |
font-family |
A font name, such as arial or times; or a generic value, such as serif or sans |
Specifies a font to be used for text in a <text> or <tspan> element. SVG has many fonts available, and it is also possible to import fonts. |
font-style |
normal | italic |oblique |
Specifies the rendering of the font face as italic, normal, or oblique. Defaults to normal. |
font-variant |
normal | small-caps |
Specifies whether lowercase text will be rendered in normal, i.e., lowercase text, or in small-caps text. Defaults to normal. |
font-weight |
normal | bold | bolder | lighter |
Specifies boldness or lightness of text. Defaults to normal. |
font-stretch |
normal | wider | narrower |
Specifies condensing or expanding of glyphs. Defaults to normal. |
font-size |
<absolute size> | <relative size> | <length> | <percentage> |
Specifies size of font. The words in brackets indicate number values. If no unit identifier is provided for number values, SVG will assume the current user unit, (pixels, unless otherwise specified in the SVG document). |
font-size-adjust |
<number> | none |
Specifies an aspect value that preserves the sizing of a font if it is necessary to substitute another font for the original font. |
These font properties are useful for fine-tuning text. Use these properties in the style attribute, both to streamline code and to keep the presentational aspects of text together.
SVG contains an attribute value called text-decoration, used for underlining or otherwise "decorating" text. The values used with text-decoration are: none | underline | overline | line-through | blink. Only the last one needs some explanation. SVG Viewers are not required to support the blink value, and as of this writing, most of them don't, so we'll leave it alone here.
Text Spacing
There are a few ways in SVG to control the space in text. You can control the space between letters and the space between words, or you can kern text. Kerning is a typesetting term that means controlling the space between glyphs in the text by means of certain proportion rules that depend on the glyphs (fonts) used. There are generally kerning tables included within each font that tell the SVG viewer how to deal with kerning.
SVG has properties that deal with these three ways of controlling spaces. They are called (appropriately enough) kerning, letter-spacing, and word-spacing. The code listed in Example 315 shows all three properties.
Example 315
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG- 20010904/DTD/svg10.dtd"> <svg width="500" height="400"> <text x="30" y="50" style="font-family:arial; font-size:19; kerning:auto">This is Kerning set to auto</text> <text x="30" y="70" style="font-family:arial; font-size:19; kerning:1">This is Kerning set to 1</text> <text x="30" y="90" style="font-family:arial; font-size:19; kerning:3">This is Kerning set to 3</text> <text x="30" y="130" style="font-family:arial; font-size:19; letter-spacing:1">This is letter-spacing set to 1</text> <text x="30" y="150" style="font-family:arial; font-size:19; letter-spacing:2">This is letter-spacing set to 2</text> <text x="30" y="170" style="font-family:arial; font-size:19; letter-spacing:3">This is letter-spacing set to 3</text> <text x="30" y="210" style="font-family:arial; font-size:19; word-spacing:1">This is word-spacing set to 1</text> <text x="30" y="230" style="font-family:arial; font-size:19; word-spacing:2">This is word-spacing set to 2</text> <text x="30" y="250" style="font-family:arial; font-size:19; word-spacing:3">This is word-spacing set to 3</text> </svg>
Figure 316 shows the results of the code in Example 315.
FIGURE 316 Kerning, letter-spacing, and word-spacing properties.
Earlier, we saw one way of rendering super- and subscripts (by using the dx and dy attributes) but there is an easier way, using the baseline-shift property. This property has values of: baseline, sub, super, <percentage number>, and <length number>. To use percentage or length, pick a positive number for a superscript and a negative number for a subscript. The baseline option sets the text back to the baseline and removes super- or subscripting. Example 316 shows the sub, super, <percentage number>, and <length number> options of the baseline-shift property.
Example 316
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="500" height="400"> <text x="30" y="50" style="font-family:arial; font-size:19">Superscript <tspan style="baseline-shift:super">super</tspan> <tspan x="30" y="90">Subscript</tspan> <tspan style="baseline-shift:sub">sub</tspan> <tspan x="30" y="130">Percentage</tspan> <tspan style="baseline-shift:20%">20%</tspan> <tspan x="30" y="170">Length</tspan> <tspan style="baseline-shift:-10">-10</tspan> </text> </svg>
Figure 317 shows the baseline shift properties.
FIGURE 317 The baseline-shift properties. From top to bottom: super, sub, <percentage number>, and <length number> (subSuper.svg).
So far, we've seen how text itself is rendered and spaced. Now we'll look at some text layout features supported in SVG.
SVG has no inherent support for line breaks or text wrapping, so multiline text layout is possible only by using multiple <text> elements or <tspan> elements embedded within <text> elements. However, SVG has sophisticated support for other aspects of text layout, including text orientation (i.e., horizontal or vertical text) and bidirectionality, (i.e., text flowing from left to right, as in English, or right to left, as in Arabic or Hebrew). In SVG, you can also render text along a path, which means the text does not flow along a strictly vertical or horizontal line.
Tables 39 and 310 show text orientation and directionality properties.
TABLE 39 Text Orientation
Orientation Property |
Value |
Description |
glyph-orientation-vertical |
auto | <angle of rotation> |
Rotates glyphs in an element according to degrees provided. The angle can be set only to 0, 90, 180, or 270 degrees. Auto is default and is equal to zero, depending on font. (Ideographic characters are treated differently than Latin characters.) |
glyph-orientation- horizontal |
<angle of rotation> |
The angle can be set only to 0, 90, 180, or 270 degrees. Orients glyphs horizontally. |
TABLE 310 Directionality
Directionality Property |
Value |
Description |
direction |
ltr | rtl |
Specifies either left to right (ltr) or right to left (rtl) direction of glyphs. English and French are examples of text that flows left to right; Arabic and Hebrew are examples of text that flows right to left. |
unicode-bidi |
normal | embed | bidi-override |
Specifies whether text will be bidirectional. If you want to set the direction of text to rtl, you must use the unicode-bidi property set to bidi-override. |
The direction and unicode-bidi properties work together to set text to flow from right to left. You need both because when the unicode-bidi property is at its default of normal, text may not always render according to the direction you set. This is because of the Unicode bidirectional algorithm, a rather complex set of rules that determine the proper directionality of text, largely based on character properties. Unfortunately, this algorithm may not produce the effect you want, so using the unicode-bidi property set to bidi-override will allow you to specify the rtl/ltr direction without interference from the Unicode standard. We'll look at Unicode in Chapter 12.
The last point is SVG's ability to lay out text along a specified path. This ability increases the artistic potential of text and makes text layout quite sophisticated!
Figure 318 shows an example of text along a curved path.
FIGURE 318 Text along a curved path.
Example 317 shows the code for the image in Figure 318. We define a path in a <defs> element and give the path an id. Starting with a <text> element, we reference within the path we just created with the <textPath> element. Like <use> and <tref>, the <textPath> element uses the xlink:href attribute to reference a piece of code defined in a <defs> element and named with an id attribute. In the case of <textPath>, we reference a curved path defined in a <defs> element and named textCurve.
Example 317
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="500" height="400"> <defs> <path id="textCurve" d="M10.5 203 C15.948 197.239 87.7676 153.791 102.5 158 C119.025 162.722 182.543 202 196.5 202 C202.451 202 242.889 237.817 297.5 156"/> </defs> <text style="font-size:18pt"> <textPath xlink:href="#textCurve">Merrily we curve along!</textPath> </text> </svg>
Please note that the path defined in Example 317 is a series of curves set by specifying coordinates and control points in the d= attribute. In Chapter 1, we saw that the d attribute is the "path data" attribute and, like polygons and polylines, contains a series of coordinates to specify where lines will be drawn. Unlike polylines and polygons, however, path data can contain curves. We'll take a closer look at paths in Chapter 4.
Internationalization
SVG can render text in fonts other than English and in directions that are compatible with many different languages. SVG uses the Unicode standard for text, which provides a character set that is virtually universal. That means that most written languages can be used to render SVG text, provided that you can find the font.
Another aspect of internationalization is SVG's ability to render documents in different languages, dependent on the system that the client machine is using. In other words, you can create a document that will render in English if the client has a system set to English, French if the client's browser is set to French, and so on, making SVG truly useful for creating sites that are to be seen internationally. This exciting feature is accessed by using SVG's systemLanguage attribute and an element called <switch>. Let's take a look at a multilingual SVG file. Example 318 shows text in English, French, and Spanish.
Example 318
<?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <svg width="500" height="400"> <text x="100" y="200" style="fill:red; font-family:arial; font-size:18; font-weight:bold" systemLanguage="en">I like SVG! </text> <switch> <text x="100" y="200" style="fill:red; font-family:arial; font-size:18; font-weight:bold" systemLanguage="fr">J'aime SVG! </text> <text x="100" y="200" style="fill:red; font-family:arial; font-size:18; font-weight:bold" systemLanguage="sp">Me gusta SVG! </text> </switch> </svg>
If you view the code in Example 318 on a system set to English as the default language, you'll see the text that says "I like SVG!" However, if you view the code in a system with the default language set to French or Spanish, you'll see either "J'aime SVG!" or "Me gusta SVG!" Fortunately, you won't see all three <text> elements at the same time because of the <switch> element. How does it work?
We created three <text> elements and set each one with a different systemLanguage attribute. The first one is set to "en" for English, the second to "fr" for French, and the third to "sp" for Spanish.
Next, we embedded our French and Spanish text into a <switch> element. The <switch> element tells SVG that only one of the elements nested within it will be rendered.
The SVG viewer reads the first systemLanguage attribute, and if the client system is set to English as its default, the English text is rendered, and the other options are ignored. If the client's system is not set to English, SVG reads through the <switch> elements. If the system is set to French, the French text is rendered, and the rest is ignored. If the system is not set to either English or French, SVG looks to see whether it is set to Spanish. If it is, the Spanish text is rendered. If the client's system is set to none of the languages we've specified, SVG will render nothing. We could add a default element within the <switch> element to display if the client's system language is not found in the code. This line of code would be placed just before the closing </switch> element tag and would read as follows:
<text x="100" y="200" style="fill:red; font-family:arial; font-size:18; font-weight:bold">Language not found.</text>
To be really correct, add a graphic element instead of text, like a large exclamation point or question mark. This may help a reader who doesn't speak English more than English text could!