Generated Content by David Storey

Vertical text with CSS 3 Writing Modes

Languages with latin-based writing systems such as English are typically written left to right, and from top to bottom. However, there is a whole different world of writing modes out there. CSS3 Writing Modes allows you to use these in your web sites. Read on to find out what you can, and can not use right now.

Introduction to writing modes

If you’re from anywhere outside of East Asia or the Middle East, it is likely that the writing mode your are most intimately familiar with is those that go from the left edge of the page to the right (line direction), and from the top of the page to the bottom (block direction). Examples of scripts that use this writing system include Latin (e.g. English, French, Spanish, etc.), Greek, Cyrillic (Russian, Ukrainian, Bulgarian, etc.), and Brahmic scripts such as Devanagari, Thai, Tibetan, and so on.

In the Middle-East (as well as North Africa, and Pakistan), the Arabic script is common, while in Israel the Hebrew script is used. Both of these scripts are written from right to left, rather than left to right as in Latin. What they do have in common with Latin scripts is that the lines progress down the page. If you look at a site set in Hebrew or Arabic, they tend to look like a mirror image of what one might expect if you come from a country that uses the Latin alphabet.

Things get a bit more complex when you look at CJK (Chinese, Japanese, and Korean), traditional Mongolian and other languages that can be written in vertical orientation. The key word is can. If you look at almost any Chinese or Japanese web site, you may notice that it is most likely written from left to right and top to bottom, just like Latin languages. While this is prevalent on the web, traditionally—and still in many printed publications—these languages were written with a line direction from top to the bottom of the page, and a block direction that goes from the right hand side of the page, to the left. Mongolian on the other hand uses the same top to bottom orientation, but the block direction goes from left to right.

I suspect one of the reasons why vertical text isn’t so prevalent on the web is that there hasn’t been high quality support for it in web browsers, and operating systems and applications in general. I would also guess there could be usability issues with scrolling. Vertical scrolling has traditionally been easier than horizontal scrolling, and you don’t want to keep scrolling up and down the page for each line. Multi-column layout on the web has similar scrolling issues. I’m mainly guessing though, as I’m not much more than a rookie in terms of when and how to use vertical rather than horizontal text in East Asian languages.

How to apply writing modes on the Web

In actual fact, we’ve been able to use vertical text longer than you might think. IE 5.5 added support for this feature, and support was upgraded in IE8. At the basic level, the support problem was that of other browsers. Things are a bit different now, as WebKit also has support. I suspect this is due to the demands of ePub for e-books, where WebKit is popular, and vertical text for the Japanese market is a key feature.

writing-mode

The property you need to use is writing-mode. The specification includes three values. While WebKit supports these values, IE support predates the latest version of the spec, and instead uses the values that were used in an older version and originate from SVG 1.1. While this isn’t ideal, they map well and work more or less in the same way.

IE supports the writing-mode property with the -ms- prefix (IE 8+) and without (since IE 5.5 when prefixes were not common), while WebKit requires the usual -webkit- prefix.

horizontal-tb

The horizontal-tb value is used for horizontal scripts with a block direction that goes from top to bottom. This is the default value, so you probably don’t need to specify it, unless you’re overriding a previously set value.

You’ll notice that the horizontal part of the keyword doesn’t specify the direction of the line of text. This can be set (if it hasn’t been already) by the good old direction property. Left to right uses the ltr keyword, and right to left uses the rtl keyword.

For IE there are two different values. Instead of using the direction property to specify the line direction, it is specified in the writing-mode value. left to right, top to bottom uses the value lr-tb, while right to left, top to bottom uses rl-tb.

Here is an example setting left to right, top to bottom text. I’ve included all prefixes, so it will also work if IE updates it’s syntax or Firefox adds support:


-ms-writing-mode: lr-tb;
-webkit-writing-mode: horizontal-tb;
-moz-writing-mode: horizontal-tb;
-ms-writing-mode: horizontal-tb;				
writing-mode: horizontal-tb;

While for right to left, top to bottom, the following code is needed:


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

direction: rtl; /* not specified as part of writing-mode property in standard syntax */

vertical-rl

This is where things get fun. The vertical-rl keyword is used to make the line direction switch in vertical mode, with a block progression from right to left. This is the value you will want to use for vertical layout in CJK languages. You do not need a direction property here as there are no known languages that uses bottom to top lines (unless you’re mixing scripts, such as embedding Arabic inside CJK text, but that is a whole different story).

IE supports this using the older tb-rl value:


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

vertical-lr

If you want to use vertical Mongolian text, you’ll want to use the vertical-lr value, or tb-lr for IE. Lines go from top to bottom like CJK languages, but they flow from the left to the right of the page.


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

Writing-mode demos

Demo of writing modes in action

You can see all four of these writing modes in action (if you’re using a modern version of IE or WebKit-based browser) in my writing modes demo. I’ve used English text in each example, but you should get the basic idea. The right to left example may be confusing though, as the text (except final punctuation and list markers) looks left to right, but right aligned. The reason is that when using Latin characters inside right to left text, they keep their left to right orientation. This is known as bi-directional text, or Bidi, but that is a discussion for another day).

Although vertical layout is primarily for languages that are naturally displayed in this orientation, Latin-based languages can also sometimes be used vertically. Usually due to lack of available space, or for stylistic reasons. Think of the spine of a book, labels on the 𝑦 axis of a graph, or those fancy vertical signs you see run down the side of theatres and other such establishments. In all but the latter case, each glyph is usually rotated 90° clockwise along with the line, so that it is displayed on its side, rather than its natural orientation. That is the default behaviour when using latin characters in vertical text using CSS.

Demo using vertical text to save space in a table heading

I’ve made a demo taking advantage of this behaviour, where I’ve rotated text in a table header to save horizontal space. View the writing-mode property support demo in WebKit or IE to see this in action.

One thing you should be aware of with the previous demo is that I had to add a span (or another element) inside the th for the vertical orientation to apply in WebKit. In IE this was not needed, but the header cell didn’t resize after rotation, leaving white space. I suspect it is a bug in both browsers, but with the way tables work, it is anyone’s guess (or at least, someone smarter than me about such things). The spec mentions that writing-mode does not apply to table rows, row groups, columns and column groups, but does not mention individual table cells. Adding an element inside the cell works in both browsers however, so this technique is viable if you don’t mind an extra element.

Demo of Japanese text in vertical orientation

Finally I’ve made a vertical text demo using Japanese text. Here you can see the vertical text writing mode used for it’s main intended purpose. Check out the Japanese vertical text demo in IE or Chrome.

The rules for vertical Japanese text are far more complex than I could ever hope to understand while working on this post, so there may be a number of issues that would look wrong to native eyes. After checking with Tomomi Imura, one such issue is with how the latin digits are rotated. In Japanese vertical layouts, these digits often keep their horizontal orientation, but with special rules, such as centring the glyph (central baseline in CSS terminology) rather than using the alphabetic baseline (the left edge of the line in top to bottom, right to left text). If two digits are found together, they are often combined side by side as if they were one glyph (know as tate-chu-yoko). While latin digits often keep their horizontal orientation, alphabetic glyphs can be rotated (as is the default) or keep their horizontal orientation. I’ve no idea what the rules are here, or if it is entirely stylistic. The main thing I have noticed is that runs of uppercase Latin characters are often set in the horizontal orientation, while lowercase characters are often in the sideways orientation. The next section will cover what we can and can’t do to correct these issues.

Changing the orientation of glyphs in vertical text

If you want to keep glyphs from scripts such as latin from rotating when in vertical mode, you can use the text-orientation property, with a value of upright:


-ms-writing-mode: tb-rl; /* old syntax. IE */
-webkit-writing-mode: vertical-rl;
-moz-writing-mode: vertical-rl;
-ms-writing-mode: vertical-rl;
writing-mode: vertical-rl; /* new syntax */
			
-webkit-text-orientation: upright;
-moz-text-orientation: upright;
-ms-text-orientation: upright;
text-orientation: upright;

This is currently only supported in WebKit browsers. You can check it out by viewing an updated version of the previous Japanese demo, using text-orientation: upright.

image

This property applies to all glyphs, but as Japanese characters are already in the horizontal orientation, you will only see a difference with the Latin characters.

As you may want to keep some non-Japanese characters in the default sideways orientation, it may be best to add spans around the glyphs you want to keep upright.

The eagle-eyed among you might notice an issue in WebKit browsers. While the digits are kept horizontal, they are still aligned to the alphabetic baseline, rather than centred to the central baseline. Chrome is also slightly clipping the text. Every glyph is also rotated, which is incorrect. Glyphs such as hyphens (-), and brackets and braces ({}()<>) should be left sideways, otherwise they look very odd.

While this is where support stops for this property in Safari, Chrome also supports the sideways and sideways-right keywords. The sideways-right value rotates the glyphs 90° clockwise when using vertical layout. This is the same as what is applied by default to horizontal scripts such as Latin. It will however also rotate glyphs that are usually displayed horizontally in vertical layout, which will probably look odd to anyone that can read those languages.

The currently unsupported sideways-left keyword rotates the glyphs 90° anti-clockwise. The text line is also rotated 180° as if the text is read bottom to top, instead of top to bottom. Think of how labels on the left hand side of the 𝑦 axis of a graph are often displayed.

Combining glyphs side-by-side in vertical text

While in vertical text glyphs progress down the page, rather than side by side, sometimes you may want to have two (or maybe more?) glyphs side by side, such as the aforementioned case where two digits are combined.

For that particular use case, we can use the following rule:


text-combine-horizontal: digits 2;

The digits 2 value (actually the 2 can be omitted, as it is the default), says that if two digits (U+0030–U+0039) or less are found in a row, combine them in the space used for 1 character (a width of 1em). Unfortunately, while this would solve our problem, it is not currently supported anywhere, to my knowledge.

The all keyword works the same way, but tries to apply it to the entire textual contents of the element. You can imagine that if you apply this to an element with more than a few characters, it is likely to not be able to do that. The spec says that it must try to fit the contents into 1em, but can use any method to do so. So I’m not exactly sure what would happen if the contents don’t fit. Craziness is my best guess.

The final value is none, which is the default. It is easy to imagine what this does (nothing, except default back to nothing if the element was previously doing something).

Some unexpected things to take into account when using vertical text

If you expect everything to work as if you just rotated the element and its children 90° using CSS transform rotate, then there are a number of things you should be aware about.

Height, width, and the box model

If you rotate an element 90° clockwise with a transform, the width of the element looks as if it is the height (width now goes from top to the bottom of the screen). With vertical text however, the width and height remain the physical width and height. That is, if you specify the width and height, the text lines will rotate when specifying vertical text, but the width and height of the element will stay the same.

Similarly, margin/border/padding-top will remain the physical top of the element, rather than the right side when an element is rotated 90° clockwise. A key difference here is margin collapsing. As text flows across the page, margin-left collapses instead of margin-bottom when using vertical-rl, and the right margin collapses when using vertical-lr.

The positioning properties such as top, right, bottom, and left also still refer to the physical edge of the element’s margin box. The top property still refers to the top edge, rather than switching to the physical right edge.

Text-align, vertical-align, text-decoration and floats

While the box model doesn’t rotate, text-align, vertical-align, text-decoration and floats do. Left aligned text will become top aligned, right aligned text will be bottom aligned. As you may have guessed by now, float: left will float the element to the physical top, while float: right will float to the physical bottom.

Vertical-align: top will align to the physical right of the cell when using vertical-rl and the physical left of the cell when using vertical-lr. Similarly, the underline value of text-decoration will be drawn along the physical left edge of the line box using vertical-rl and the physical right side when using vertical-lr.

Due to the above, the vertical-align property is unfortunately named, as are the left and right values of text-align and float. For text-align, two new abstract keywords have been defined, named start and end. The start value is the equivalent of left and end is the equivalent of right (except when using the right to left line direction (e.g. Arabic or Hebrew), where start is right, and end is left). This makes their use less confusing, as they always apply to the start and end of the line box, no matter what orientation is being used. These are currently only supported by WebKit and Gecko. Similarly the abstract values for top and bottom are over and under respectively.

All of this might be easier to understand with a diagram, so here you go:

Abstract and physical dimensions and directions

Flow relative directions

The following diagrams show the mapping between the flow relative abstract (yellow) and physical (green) directions, as well as the dimensions of the element. The physical directions always stay the same, while the logical directions change depending on writing mode, direction and text orientation.

horizontal-tb ltr (left to right, top to bottom)

horizontal-tb rtl (right to left, top to bottom)

vertical-rl (top to bottom, right to left)

vertical-lr (top to bottom, left to right)

Line relative directions

The following diagrams show the line relative physical (blue) and abstract (yellow) directions. You will notice that the physical line-relative directions do change when the text orientation is flipped from sideways-right to sideways-left.

horizontal-tb (top: ltr, bottom: rtl)

vertical-lr and vertical-rl

  1. text-orientation: sideways-right, direction: ltr
  2. text-orientation: sideways-right, direction: rtl
  3. text-orientation: sideways-left, direction: ltr
  4. text-orientation: sideways-left, direction: rtl
  1. silencespainter reblogged this from dstorey
  2. chashishi reblogged this from dstorey
  3. sgautam reblogged this from dstorey and added:
    Primer on css3 writing modes
  4. dstorey posted this