How To Adjust The Baseline Alignment Of SVG Text

When you set coordinates to position SVG text, you’re setting the location of the left edge of the text and you’re setting the location of the baseline of the font. Last week I showed how you could adjust the former through the text-anchor attribute and today I want to show you how you can adjust the latter.

If you haven’t been following along with this series about SVG text you may want to read the first post where I talk about things like font tables and EM boxes. I’ll do my best to to keep things clear in this post, but an understanding of what’s in the earlier post will probably be helpful.

Baseline Alignment

In the first post in this series I talked a little about font tables and how they include information such as the position to display the font’s glyphs. Information about the location of the baseline of the glyph in relation to the EM box is part of the information in the tables.

Different fonts can have different baselines and so different points where they’re located within the EM box. For example:

  • horizontal writing, ideographic scripts (Han Ideographs, Katakana, Hiragana, and Hangul) are aligned to a baseline near the bottom of the glyph.
  • alphabetic based scripts (Latin, Cyrillic, Hebrew, Arabic) are aligned to a baseline at the bottom of most glyphs, but some glyphs descend below the baseline.
  • Indic based scripts on the other hand are aligned at a point that is near the top of the glyphs.

If you stick with a single font there’s no issue, but if you change fonts along the line it is. Changing fonts is possibly more realistic than you realize too.

For example it’s not uncommon for two words in a logo to use different fonts or you might switch to a monospaced font to show code in the middle of a sentence. Depending on the fonts in question they might not align along the same baseline.

SVG uses a model that assumes a single font at a single size is the “dominant run” and all other baselines are defined in relation to it. Each font should provide information about offsets for the alternate baselines as well as an offset for math baselines in some math fonts.

The model further assumes each glyph has an alignment-baseline value to align the baseline of that glyph with the dominant baseline.

It’s possible your head might be spinning after reading everything to this point. I know mine was when I first looked at baseline alignment and it’s still spinning just a little so I’ll skip further details.

The gist is the font tables associated with each font contain information about different baselines the glyphs might be aligned to and SVG uses the information to align the glyphs in different fonts relative to each other.

Baseline Alignment Properties

SVG provides three properties to allow you adjust these different baselines.

  • dominant-baseline – used to determine or re-determine a scaled-baseline-table
  • alignment-baseline – specifies which baseline is to be aligned with the corresponding baseline of the parent
  • baseline-shift – allows repositioning of the dominant-baseline relative to the dominant-baseline of the parent

My guess is, the last baseline-shift is the one you’ll be tempted to use the most, but let me offer an example of each to try to illustrate how each can be used to refine the location of the baseline of the font you’re using.

dominant-baseline

The dominant-baseline property can take any of the following values auto, use-script, no-change, reset-size, ideographic, alphabetic, hanging, mathematical, central, middle, text-after-edge, text-before-edge, inherit.

Instead of copying and pasting the definition of each I’ll point you to the definitions in the spec. I’ll present an example showing some of the values. I should mention the examples in this post won’t work in Firefox, but they do work in Safari and Chrome. I haven’t tested in other browsers.

In this example I created what should be a familiar <svg> element with viewport dimensions set along with some styles I hope are self-explanatory.

Inside the SVG I created six <text> elements. The first three are positioned so their default baseline sits on the top edge of the viewport and the last three on top of the bottom edge of the viewport.

1
2
3
4
5
6
7
8
<svg width="660" height="220" style="outline: 1px solid red; font-size: 1.5em; overflow: visible;">  
  <text x="0" y="0">SVG</text>  
  <text x="100" y="0" dominant-baseline="hanging">SVG (hanging)</text>  
  <text x="300" y="0" dominant-baseline="mathematical">SVG (mathematical)</text>  
  <text x="0" y="220" dominant-baseline="central">SVG (central)</text>  
  <text x="200" y="220" dominant-baseline="middle">SVG (middle)</text>  
  <text x="400" y="220" dominant-baseline="text-before-edge">SVG (text-before-edge)</text>  
</svg>

The dominant-baseline of the first <text> element hasn’t been adjusted. The other five have and I placed the value in parenthesis so you can see the value used.

SVGSVG (hanging)SVG (mathematical)SVG (central)SVG (middle)SVG (text-before-edge)

If you’d like to see examples of the other values you can play around with the code or check here. If you do the latter the same browser warning from above applies.

alignment-baseline

The alignment-baseline property takes a similar set of values. They are auto, baseline, before-edge, text-before-edge, middle, central, after-edge, text-after-edge, ideographic, alphabetic, hanging, mathematical, and inherit.

Again I’ll refrain from copying and pasting definitions of the values and point you one more time to the spec. I will present another example similar to the previous one, but using alignment-baseline instead of dominant-baseline.

The SVG element is the same as before. Because alignment-baseline is an adjustment relative to the parent element, I created two text elements, one at the top and one at the bottom and inside each I placed several tspan elements with different alignment-baseline values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<svg width="660" height="220" style="outline: 1px solid red; font-size: 1.25em; overflow: visible;">  
  <text x="0" y="0">SVG  
    <tspan alignment-baseline="baseline">SVG (baseline)</tspan>  
    <tspan alignment-baseline="middle">SVG (middle)</tspan>  
    <tspan alignment-baseline="central">SVG (central)</tspan>  
    <tspan alignment-baseline="hanging">SVG (hanging)</tspan>  
  </text>

  <text x="0" y="220">SVG  
    <tspan alignment-baseline="before-edge">SVG (before-edge)</tspan>  
    <tspan alignment-baseline="after-edge">SVG (after-edge)</tspan>  
    <tspan alignment-baseline="mathematical">SVG (mathematical)</tspan>  
  </text>  
</svg>

Again the value I used is in parenthesis to help you see the value as you’re looking at the result.

SVGSVG (baseline)SVG (middle)SVG (central)SVG (hanging)SVGSVG (before-edge)SVG (after-edge)SVG (mathematical)

I’ll leave it to you to try the values I didn’t use in these examples if you want to see what each does or you can check here with the same browser warning.

baseline-shift

Of the three baseline alignment properties, baseline-shift is probably the one you’ll use most often and it has the fewest possible values.

The baseline-shift property “allows repositioning of the dominant-baseline relative to the dominant-baseline of the parent text content element.” In other words it lets you shift text up or down or rather perpendicular to the direction the text flows when displayed.

The baseline-shift property takes four values (sub, super, <percent>, <length>) and the first two will give you an idea when and why you’d want to use the property. With the latter two values, a positive value moves the text up (super) and negative value moves down (sub).

In this next example I created four text elements, each with a <tspan> inside containing the number 2. I added the following baseline-shifts to the tspans from top to bottom in the code, sub, super, –60%, and 20px. The last two values I adjusted by eye to hopefully match the sub and super values.

1
2
3
4
5
6
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="120" y="100">SVG<tspan baseline-shift="sub">2</tspan></text>  
  <text x="220" y="100">SVG<tspan baseline-shift="super">2</tspan></text>  
  <text x="320" y="100">SVG<tspan baseline-shift="-60%">2</tspan></text>  
  <text x="420" y="100">SVG<tspan baseline-shift="20px">2</tspan></text>  
</svg>

SVG2SVG2SVG2SVG2

Closing Thoughts

My apologies for what might be another information dense and mostly dry post. My eyes glazed over a bit when I first took a look at the spec, but it’s ultimately not all that complicated.

Fonts deliver information through font tables about where their glyphs should be positioned, including where the baseline of the glyph should be positioned.

Because different fonts will have different baseline information it’s possible when using multiple fonts that they won’t line up the way you want. When that happens you can adjust the three baseline properties so the glyphs are better aligned.

Next week I’ll take a look at some properties you likely use all the time in CSS and show you how to apply them to SVG. We’ll talk about font properties you know like font-family and font-size and some you might not know like font-stretch.

Download a free sample from my book, Design Fundamentals.

6 comments

  1. Hi Steve,

    First of all thanks for the awesome blogs on SVG Text elements, they are really helpful 🙂

    Just found one thing, that the attribute dominant-baseline is actually working in Firefox but not for Safari.

    please see https://jsfiddle.net/zegkt4uz/5/

    Best Regards
    Peter

    • Thanks Peter. I see what you mean. I’ve noticed while working on this and other SVG series that some browsers don’t always behave quite like you expect or hope they will.

    • I used this:

      dominant-baseline=”hanging” alignment-baseline=”text-before-edge”

      to get around the cross browser issues.

  2. I am not normally one to ‘leave a reply’, however, I was able to fix my firefox rendering problems thanks to this article and the ‘tspan’ discovery is great news for me. Thanks for the article!

Leave a Reply

Your email address will not be published. Required fields are marked *