Generated Content by David Storey

Vertical text update: text-combine-horizontal

In a previous blog post, I covered vertical text using CSS writing modes. At that time, it was possible to use vertical text in both IE (and has been since version 5.5) and WebKit. Since Opera switched to Blink, it now also joins that list. However, at that time, the support for more advanced control of glyphs within a vertical layout was very limited.

While the support does remain limited, the IE11 preview has become the first browser to support the text-combine-horizontal feature. I will show you this feature in this blog post; but first, a brief overview of how to use vertical text.

Setting text layout to vertical

Vertical layout can be achieved by using the writing-mode property. When text is laid out vertically, lines of text can proceed from right to left (as in CJK languages), or left to right (traditional Mongolian).

In the W3C Writing Modes specification, top to bottom, right to left text can be achieved using the vertical-rl value. IE implemented this before the current spec, and thus uses an older syntax–tb-rl–that came from SVG:

-ms-writing-mode: tb-rl; 
-webkit-writing-mode: vertical-rl;
-moz-writing-mode: vertical-rl;
-ms-writing-mode: vertical-rl;
writing-mode: vertical-rl;

The less used top to bottom, left to right orientation can be achieved with vertical-lr and tb-lr for IE.

Glyph orientation

Outside of Asian languages like Chinese and Japanese, it is not customary to write using a vertical layout, but it is not unheard of. The Coke can sitting next to me has “Coca-Cola Zero” writen vertically, bottom to top, left to right. If you walk through any major city and look up at store signs, you’ll often see vertical text to save space. You’ll also see it on spines of books. In Asian vertical layouts, you will often see Latin (or other scripts) mixed in with the native script. In all these cases, there needs to be some control of the glyph orientation.

As far as I know, East Asian scripts always orientate there characters horizontally; they don’t flip on their side when displayed vertically. Latin characters can either be flipped on their side, following the direction of the text (such as on the aformentioned Coke can) or left upright, as seen on many store signs.

If you read my previous post, you’ll know that you can set the glyph orientation with the text-orientation property. Support for this hasn’t changed; it is still only supported in WebKit/Blink, and it still only has partial support. The upright value for keeping all glyphs in the horizontal orientation is the most important one for this article.

Combining upright characters

While by default characters are displayed one after another in the direction of the line, it is often desirable to display two or more side by side when using vertical text. A common example of this is Latin numbers in dates; instead of the digits in the month or day being displayed one after another, they are combined as if they were one character (actually 1em) wide.

IE11 adds support for the text-combine-horizontal property which enables this feature. There are two different modes, which act fairly differently, so it is important to understand how they work.

Combining digits

When you just want to combine digits, such as in our date example, you can use text-combine-horizontal: digits. By default this combines any two digits or less that are found together. If you specify a number after the digits keyword, it combines up to that many digits. The upper limit is 4. The glyphs are orientated upright, even if text-orientation is not applied, which is just as well, as IE doesn‘t support that property.

text-combine-horizontal: digits; /* combines runs of 1–2 digits (0–9) together*/
text-combine-horizontal: digits 2; /* same as above */
text-combine-horizontal: digits 4; /* combines runs of 1–4 digits */

The following example is inspired by a Mexican street sign found in Thinking with Type. The text-combine-horizontal: digits; declaration is used to combine each set of two digits in a 1em by 1em square, with the glyphs orientated horizontally:

Mexican street sign demo

There are some things to note here:

It is also important to be careful when using this feature. While it only works on digits, sometimes long strings of digits are pretty printed to make them easier to read (as you will have seen in my Internationalization article). CJK languages use a comma for this. As this will split a run of digits, you may get part of the number combined and the rest left in the default state. The number 10,000,000 will combine 10 and leave the rest untouched. For this reason, it may be best, if you are likely to have situations like this, to use an inline element such as a span around digits you want to combine. This can be seen in a demo I updated from the previous vertical text article:

Japanese vertical text demo, with text-combine-horizontal

In this demo I combine any 3 digits or less that are found together. I highlighted all the digits in spans in red to be easier to find. Changing the value to 4 will combine the years as well. When four digits get combined, they can get quite compressed, so it is probably only wise to do this far large text sizes.

A couple of issues I found when making the previous demos is that IE applies any text-indent to text that has text-combine-horizontal applied (even if text-indent is only applied to the element’s parent), so this has to be cancelled out; and text-combine-horizontal is not applied to inline elements, even when directly specified on that element. Applying display: inline-block fixes this:

section span {
    /* make IE apply text-combine-horizontal to a span */
    display: inline-block; 
    /* remove text-indent that was applied on parent */
    text-indent: 0;

    -webkit-text-combine-horizontal: digits 4;
    -moz-text-combine-horizontal: digits 4;
    -ms-text-combine-horizontal: digits 4;
    text-combine-horizontal: digits 4;
    color: red;
}

One could take the opposite approach, and wrap the text you don’t want combined in spans, but in my case that wouldn’t work unless I remove the text-indent. If you do this, it is important to set text-combine-horizontal: none on the span, as if the spec is changed so that inheritance is allowed, it will suddenly break. Better to be safe than sorry.

Combining all text in an element

While the digits value only works on, well, digits, you can use the all value for any character. However, it is not that simple. It doesn’t look for runs of characters inside the element and look to combine them, but instead, it tries to combine the entire text content of the element. As with the digits value, the advance width of the result has to fit within a 1em square. As you can imagine, for a few characters that is pretty easy; a number of fonts even have half-width, third-width and quarter-width variants for certain glyphs; but for longer text, it is going to become unreadable quite fast. This text-combine-horizontal: all demo shows this in action.

Something important to point out is that this only works with (non-replaced) inline elements, unlike the digits value, which works in the polar opposite way in IE. I think this is fine, as you’re likely to be individually marking things up where this is to apply to when it works the way it does with all text in the element. It is also not applied if the element contains any child elements.

If you remember our earlier issue with the “Z” that didn’t rotate in the Mexican banner example, you will probably now see how that can be fixed using a span and text-combine-horizontal: all:

Mexican banner with Z in the correct orientation

HTML

<h1><span>Z</span> 44 82 98</h1>

CSS

h1 {-ms-writing-mode: tb-rl;
    -webkit-writing-mode: vertical-rl;
    -moz-writing-mode: vertical-rl;
    -ms-writing-mode: vertical-rl;
    writing-mode: vertical-rl;

    /* only currently works in Blink/WebKit */
    -webkit-text-orientation: upright;
    -moz-text-orientation: upright;
    -ms-text-orientation: upright;
    text-orientation: upright;

    /* only currently works in IE11 */
   -webkit-text-combine-horizontal: digits;
   -moz-text-combine-horizontal: digits;
   -ms-text-combine-horizontal: digits;
   text-combine-horizontal: digits;

}

h1 span {
    /* Sets upright orientation for the Z */
    -ms-text-combine-horizontal: all;
}

As you can perhaps see, WebKit/Blink can use text-orientation: upright; to make the Z glyph display upright. I’m a little suprised that Microsoft added text-combine-horizontal without adding text-orientation and updating the values used by writing-mode. Perhaps for IE12?

  1. maxw3st reblogged this from dstorey
  2. dstorey posted this