writing-mode & text-orientation
writing-mode controls the direction in which text lines are laid out — horizontally (the default in Latin scripts) or vertically (used in CJK scripts like Japanese and Traditional Chinese). text-orientation controls how individual characters are rotated within a vertical line. These properties are also used creatively in web design to create sideways text labels for vertical tabs and rotated headings.
writing-mode
CSS
/* Horizontal (default) — text flows left-to-right, lines stack top-to-bottom */ writing-mode: horizontal-tb; /* horizontal, top-to-bottom block direction */ /* Vertical — text flows top-to-bottom, lines stack right-to-left */ writing-mode: vertical-rl; /* vertical, right-to-left line progression */ /* Vertical — text flows top-to-bottom, lines stack left-to-right */ writing-mode: vertical-lr; /* vertical, left-to-right line progression */ /* Sideways — same as vertical-rl but all glyphs are rotated upright */ writing-mode: sideways-rl; writing-mode: sideways-lr;
text-orientation
CSS
/* text-orientation only applies in vertical writing modes */ text-orientation: mixed; /* default — upright CJK, rotated Latin */ text-orientation: upright; /* all characters upright, even Latin letters */ text-orientation: sideways; /* all characters rotated 90deg */ /* mixed is the correct default for Japanese text — kanji sit upright, Latin letters rotate 90deg to read normally */
Sideways tab labels — a practical use case
writing-mode is frequently used in CSS for rotated tab labels, sidebar headings, and vertical text annotations. The key insight is that width and height swap their block/inline role:
CSS
/* Vertical tab label — text reads bottom-to-top */
.tab-label {
writing-mode: vertical-rl;
transform: rotate(180deg); /* flip so text reads bottom-to-top instead of top-to-bottom */
white-space: nowrap; /* prevent the vertical text from wrapping */
}
/* Left-aligned sidebar section title */
.sidebar-title {
writing-mode: vertical-lr;
text-orientation: mixed;
}
/* Decorative vertical headline */
.vertical-hero-text {
writing-mode: vertical-rl;
text-transform: uppercase;
letter-spacing: 0.2em;
font-size: 0.75rem;
}
/* Note: in vertical writing mode, width and height swap
A 100px height becomes the inline (text-flow) dimension
A 200px width becomes the block dimension */In vertical writing mode, width becomes the block axis and height becomes the inline axis — logical properties (block-size, inline-size) are safer to use
When you apply `writing-mode: vertical-rl` to an element, what was previously the horizontal direction is now the block direction, and vertical is the inline direction. Physical properties like `width` and `height` work fine but can be confusing. Logical properties — `block-size` (equivalent to height in horizontal, width in vertical) and `inline-size` (width in horizontal, height in vertical) — stay meaningful regardless of writing mode.
CJK vertical text
CSS
/* Traditional Japanese/Chinese vertical text */
.japanese-article {
writing-mode: vertical-rl;
/* Japanese flows right-to-left, top-to-bottom */
}
.japanese-article p {
text-orientation: mixed; /* kanji upright, Latin rotated */
}
/* Punctuation that should be upright */
/* Japanese fullwidth punctuation is automatically handled by the browser */
/* For primarily Latin text read vertically */
.rotated-english {
writing-mode: vertical-lr;
text-orientation: sideways; /* rotate all characters consistently */
}
/* Or use transform rotate as an alternative for purely decorative text */
.rotated-label {
transform: rotate(-90deg); /* visually rotated but still horizontal mode */
white-space: nowrap;
}Logical properties and writing mode
CSS logical properties automatically adapt to the writing mode, making them essential for truly internationalised layouts:
CSS
/* Physical properties — don't adapt to writing mode */
p { margin-top: 1em; padding-left: 1rem; }
/* Logical properties — adapt to writing mode */
p {
margin-block-start: 1em; /* 'before' the text flow direction */
padding-inline-start: 1rem; /* 'start' of the inline direction */
}
/* In horizontal-tb: block-start = top, inline-start = left
In vertical-rl: block-start = right, inline-start = top
In RTL Arabic: block-start = top, inline-start = right */Next
Single font files that contain entire type families — how variable fonts work and how to use them: [Variable Fonts](/css/variable-fonts).