CSS Writing Mode & Direction Reference
Explore writing-mode, direction, and text-orientation — with live preview, logical property mappings, and CSS code generation for every writing system
writing-mode
Latin, Cyrillic, Greek, Devanagari, Thai, Chinese, Japanese, Korean
The element does not open a new level of bidirectional embedding. Text reorders according to the Unicode Bidirectional Algorithm.
horizontal-tb
Text flows left-to-right or right-to-left horizontally. New lines stack top to bottom. The default for Latin and most Western scripts.
Use case: Latin, Cyrillic, Greek, Arabic, Hebrew, Devanagari scripts
.my-element {
writing-mode: horizontal-tb;
direction: ltr;
}All Writing Modes — Side by Side
You’re building a Japanese vertical text layout for a literary website. You set writing-mode: vertical-rl and the text flows top-to-bottom, columns right-to-left — correct. But now your margin-left is actually adding space at the top of the text block, width controls the block dimension instead of the inline dimension, and your Flexbox axis is rotated 90°. Every physical CSS property maps differently in vertical writing modes, and the only way to understand the mappings is to see them.
Why This Reference (Not the Logical Properties Guide)
PureDevTools has a CSS Logical Properties Reference that maps physical to logical properties. This reference goes deeper: it covers all three writing-mode values (horizontal-tb, vertical-rl, vertical-lr), direction (ltr/rtl), text-orientation (mixed, upright, sideways), unicode-bidi, and how each combination affects logical property resolution. Interactive demos let you toggle modes and see the effect live. Everything runs in your browser; no data is sent anywhere.
What Are CSS Writing Modes?
CSS writing modes control how text flows on a page — the direction of lines, which axis text advances along, and how characters are oriented. Three core properties work together:
writing-mode— defines whether lines of text are laid out horizontally or vertically, and the direction in which blocks progressdirection— specifies whether text within a line flows left to right (ltr) or right to left (rtl)text-orientation— in vertical writing modes, controls whether characters are upright, rotated, or sideways
These properties are essential for building truly internationalized websites that support scripts from Arabic and Hebrew to Japanese and Mongolian.
The writing-mode Property
The writing-mode property accepts five values:
| Value | Text Flow | New Lines | Primary Use |
|---|---|---|---|
horizontal-tb | Left or right horizontally | Top to bottom | Latin, Arabic, Hebrew, Devanagari |
vertical-rl | Top to bottom vertically | Right to left | Chinese, Japanese (tategumi) |
vertical-lr | Top to bottom vertically | Left to right | Mongolian script |
sideways-rl | Top to bottom (rotated 90° CW) | Right to left | Sidebar labels |
sideways-lr | Bottom to top (rotated 90° CCW) | Left to right | Rotated design elements |
horizontal-tb (Default)
horizontal-tb is the default value for all elements. Text flows horizontally — left-to-right for Latin scripts, right-to-left for Arabic and Hebrew — and new lines stack from top to bottom. The vast majority of web content uses this mode.
.latin-content {
writing-mode: horizontal-tb;
direction: ltr;
}
.arabic-content {
writing-mode: horizontal-tb;
direction: rtl;
}
vertical-rl — Traditional East Asian
vertical-rl flows text top-to-bottom in vertical columns, with each new column added to the left of the previous one (right to left). This is the standard mode for Traditional Chinese books, newspapers, and Japanese tategumi (縦組み) composition.
.japanese-vertical {
writing-mode: vertical-rl;
text-orientation: mixed; /* CJK upright, Latin rotated */
}
.chinese-traditional {
writing-mode: vertical-rl;
text-orientation: upright; /* All characters upright */
}
vertical-lr — Mongolian Script
vertical-lr flows text top-to-bottom in vertical columns, with new columns added to the right (left to right). The Mongolian script is written this way — unique among all major writing systems in using vertical lines that progress left to right.
.mongolian-text {
writing-mode: vertical-lr;
text-orientation: mixed;
}
sideways-rl and sideways-lr
The sideways-* values rotate the entire line including all glyphs — unlike vertical-rl/lr where CJK characters remain upright. sideways-rl rotates text 90° clockwise, and sideways-lr rotates it 90° counter-clockwise. These are useful for sidebar labels and rotated design elements without using transform: rotate().
.sidebar-label-clockwise {
writing-mode: sideways-rl;
}
.sidebar-label-counter {
writing-mode: sideways-lr;
}
Browser support note: sideways-rl has partial Chrome/Edge support. sideways-lr is currently Firefox-only. Use vertical-rl with text-orientation: sideways as a more compatible alternative.
The direction Property
The direction property controls the inline base direction — which end of a line text starts from. It works within any writing-mode.
/* Latin, Greek, Cyrillic, CJK */
.ltr-text { direction: ltr; }
/* Arabic, Hebrew, Persian, Urdu */
.rtl-text { direction: rtl; }
Important: For HTML content, always set directionality using the dir HTML attribute (dir="rtl") rather than CSS alone. CSS direction is intended for cases where HTML attributes cannot be used. The Unicode Bidirectional Algorithm handles mixed scripts automatically.
<!-- Preferred approach -->
<html lang="ar" dir="rtl">
<p dir="rtl">نص عربي</p>
<!-- CSS-only fallback -->
<p class="rtl-text">نص عربي</p>
The text-orientation Property
text-orientation applies only to vertical writing modes (vertical-rl and vertical-lr). It controls how individual characters are oriented within a vertical line.
mixed (Default)
Characters from horizontal scripts (Latin, Greek, Cyrillic) are rotated 90° clockwise. CJK characters remain upright. This matches how Japanese tategumi works — kanji and kana are upright, while embedded Latin words rotate.
upright
All characters — including Latin letters — are rendered upright without rotation. Latin letters stack vertically one per line. Use this when embedded abbreviations like “DVD” or “API” should display as stacked upright characters rather than rotated sideways.
sideways
All characters are rendered as in a horizontal line and then rotated 90° clockwise as a unit. The result is similar to sideways-rl but applied at the character level. Use for vertical sidebar text that should read as a rotated label.
.vertical-mixed {
writing-mode: vertical-rl;
text-orientation: mixed; /* 漢字 upright, latin rotated */
}
.vertical-upright {
writing-mode: vertical-rl;
text-orientation: upright; /* all chars upright */
}
.vertical-sideways {
writing-mode: vertical-rl;
text-orientation: sideways; /* all chars rotated together */
}
The unicode-bidi Property
unicode-bidi works with direction to handle bidirectional text. The Unicode Bidirectional Algorithm (UBA) normally handles mixed LTR/RTL text automatically. unicode-bidi lets you override or customize that behavior.
| Value | Effect |
|---|---|
normal | Default — rely on the Unicode Bidirectional Algorithm |
embed | Open an additional embedding level (for inline elements) |
isolate | Isolate the element from surrounding bidi context |
bidi-override | Force strict directional ordering of all characters |
isolate-override | Combine isolation + override |
plaintext | Determine direction from text content (ignores inherited direction) |
For user-generated content of unknown direction, isolate is recommended:
/* Safe for user-generated content */
.user-content {
unicode-bidi: isolate;
}
/* Force all characters LTR (e.g., phone numbers in RTL context) */
.phone-number {
direction: ltr;
unicode-bidi: embed;
}
CSS Logical Properties
Traditional CSS uses physical properties (margin-left, padding-top, border-right) that are tied to the physical viewport. Logical properties use flow-relative terms that automatically adapt to any writing mode and direction:
- inline axis — the axis along which text flows within a line (horizontal in
horizontal-tb) - block axis — the axis along which lines/blocks stack (vertical in
horizontal-tb)
Key Logical Property Pairs
/* Physical: breaks when writing-mode changes */
.box {
margin-left: 1rem; /* always left, even in RTL */
padding-top: 0.5rem;
border-right: 2px solid;
width: 300px;
}
/* Logical: adapts to any writing mode + direction */
.box {
margin-inline-start: 1rem; /* left in LTR, right in RTL, top in vertical */
padding-block-start: 0.5rem; /* top in horizontal, varies in vertical */
border-inline-end: 2px solid;
inline-size: 300px; /* width in horizontal, height in vertical */
}
Logical Properties Quick Reference
| Logical | horizontal-tb LTR | horizontal-tb RTL | vertical-rl |
|---|---|---|---|
inline-size | width | width | height |
block-size | height | height | width |
margin-inline-start | margin-left | margin-right | margin-top |
margin-inline-end | margin-right | margin-left | margin-bottom |
margin-block-start | margin-top | margin-top | margin-right |
padding-inline-start | padding-left | padding-right | padding-top |
border-inline-end | border-right | border-left | border-bottom |
inset-inline-start | left | right | top |
Writing Systems and Their CSS Settings
Different writing traditions require specific CSS configurations:
| Script / Language | writing-mode | direction | text-orientation |
|---|---|---|---|
| Latin (English, etc.) | horizontal-tb | ltr | mixed |
| Arabic, Persian, Urdu | horizontal-tb | rtl | mixed |
| Hebrew, Yiddish | horizontal-tb | rtl | mixed |
| Traditional Chinese | vertical-rl | ltr | mixed |
| Japanese (tategumi) | vertical-rl | ltr | mixed |
| Mongolian | vertical-lr | ltr | mixed |
| Devanagari (Hindi) | horizontal-tb | ltr | mixed |
| Korean (modern) | horizontal-tb | ltr | mixed |
Frequently Asked Questions
What is the difference between writing-mode and direction?
writing-mode defines the overall text flow orientation: horizontal (default) or vertical. direction specifies which end of a line text starts from: left-to-right (ltr) or right-to-left (rtl). They are orthogonal — you can have writing-mode: vertical-rl with either direction: ltr (standard for CJK) or direction: rtl.
When should I use logical properties instead of physical properties?
Use logical properties whenever your site supports multiple languages with different writing directions, or when you want your layout to correctly adapt to vertical writing modes used in East Asian typography. Logical properties are also recommended by the CSS Working Group as the future-proof standard for all new CSS — even for monolingual Latin sites, they improve maintainability.
How do I make Arabic or Hebrew text render correctly in CSS?
Set direction: rtl on the container (or use dir="rtl" in HTML, which is preferred). The Unicode Bidirectional Algorithm handles mixed LTR/RTL content within the container automatically. For the root element, set lang and dir on <html>: <html lang="ar" dir="rtl">.
Does writing-mode affect Flexbox and Grid?
Yes. In vertical writing modes, the axes flip: flex-direction: row will lay items out vertically, and flex-direction: column will lay them horizontally. Logical properties (justify-content, align-items) stay consistent because they use the inline/block axes, which already account for writing mode.
What is the difference between vertical-rl and sideways-rl?
In vertical-rl, CJK characters are upright and Latin/Greek characters are rotated 90° (if text-orientation: mixed). In sideways-rl, every character — including CJK — is rotated 90° clockwise as if the entire text block was rotated. Use vertical-rl for genuine vertical CJK/Japanese text, and sideways-rl (or vertical-rl with text-orientation: sideways) for rotated sidebar labels.
How do text-align: start and text-align: end work?
text-align: start aligns text to the start of the inline axis — left in LTR, right in RTL. text-align: end aligns to the end — right in LTR, left in RTL. These are the logical equivalents of text-align: left and text-align: right, and they automatically adapt to the current direction. Always prefer start/end over left/right in i18n-aware code.