What CSS writing modes control
Writing modes generalise CSS layout beyond left-to-right horizontal text. The
writing-mode property sets which way blocks stack and lines flow, direction
sets right-to-left vs left-to-right inline progression, and text-orientation
rotates glyphs in vertical modes. Together they define the block axis and
inline axis that logical properties follow. This reference lists every value
with the axes it produces.
How it works
writing-mode establishes two axes. The block axis is the direction new lines
(blocks) advance; the inline axis is the direction characters within a line
advance. direction flips the inline axis for RTL scripts:
.cjk {
writing-mode: vertical-rl; /* lines run top→bottom, columns right→left */
text-orientation: mixed; /* CJK upright, Latin rotated */
}
.arabic {
direction: rtl; /* inline axis runs right→left */
}
/* logical property — follows the mode automatically */
.box { margin-inline-start: 1rem; }
In horizontal-tb ltr, inline-start resolves to left and block-start
to top. Switch to vertical-rl and the same logical properties remap to
physical edges automatically — so a single rule lays out correctly in any mode.
Writing-mode values at a glance
| Value | Block axis | Inline axis | Typical use |
|---|---|---|---|
horizontal-tb | top → bottom | left → right (or RTL) | Latin, Cyrillic, Arabic default |
vertical-rl | right → left | top → bottom | Traditional CJK |
vertical-lr | left → right | top → bottom | Mongolian, rotated UI labels |
sideways-rl | right → left | top → bottom | Latin text rotated 90° clockwise |
sideways-lr | left → right | top → bottom | Latin text rotated 90° counter-clockwise |
sideways-rl and sideways-lr treat every glyph as if it were a single upright
unit; unlike vertical-rl with text-orientation: mixed, CJK characters are
also rotated in sideways modes.
Logical properties and why they matter
Before logical properties, you had to write separate CSS for each writing mode:
/* Physical — must override for vertical text */
.box { margin-left: 1rem; padding-top: 0.5rem; }
/* Logical — works in any writing mode automatically */
.box { margin-inline-start: 1rem; padding-block-start: 0.5rem; }
The physical-to-logical mapping depends on the current writing mode:
| Logical property | horizontal-tb ltr | vertical-rl |
|---|---|---|
margin-block-start | margin-top | margin-right |
margin-inline-start | margin-left | margin-top |
border-block-end | border-bottom | border-left |
inset-inline | left + right | top + bottom |
Using logical properties is the correct approach for any component that may be dropped into different writing contexts — a reusable card, a form field, or a component library.
text-orientation in detail
text-orientation only has an effect in a vertical writing-mode. Its three
values handle a real typographic problem: should a Japanese paragraph with embedded
English acronyms stand the English letters sideways or upright?
mixed(default): keeps CJK characters upright, rotates other scripts 90°. Matches real-world vertical Japanese typesetting.upright: stands every character up, treating it as a full-width CJK block. Gives a blocky, stylised look; numbers inuprightmode are rendered as full-width digits.sideways: rotates every character 90° clockwise as a single unit. Useful for short UI labels, vertical axis titles in charts, or rotated table headers.
Tips and notes
- Prefer logical properties (
margin-inline,inset-block,border-inline-start) over physical ones for international layouts. text-orientationonly affects vertical writing modes; it is ignored inhorizontal-tb.vertical-rlis the traditional CJK default;vertical-lradvances columns left-to-right.- Combine
writing-mode: sideways-lrwith rotated table headers for compact, readable vertical labels. - Setting
writing-modeon thehtmlorbodyelement changes the block axis for the entire page, which affects scrollbar placement and layout roots — test thoroughly before applying globally.