PureDevTools

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

All processing happens in your browser. No data is sent to any server.

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.

The quick brown fox jumps over the lazy dog

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.

Inline axishorizontal (left ↔ right)
Block axisvertical (top → bottom)
Browser supportAll modern browsers

Use case: Latin, Cyrillic, Greek, Arabic, Hebrew, Devanagari scripts

Quick CSS
.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:

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:

ValueText FlowNew LinesPrimary Use
horizontal-tbLeft or right horizontallyTop to bottomLatin, Arabic, Hebrew, Devanagari
vertical-rlTop to bottom verticallyRight to leftChinese, Japanese (tategumi)
vertical-lrTop to bottom verticallyLeft to rightMongolian script
sideways-rlTop to bottom (rotated 90° CW)Right to leftSidebar labels
sideways-lrBottom to top (rotated 90° CCW)Left to rightRotated 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.

ValueEffect
normalDefault — rely on the Unicode Bidirectional Algorithm
embedOpen an additional embedding level (for inline elements)
isolateIsolate the element from surrounding bidi context
bidi-overrideForce strict directional ordering of all characters
isolate-overrideCombine isolation + override
plaintextDetermine 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:

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

Logicalhorizontal-tb LTRhorizontal-tb RTLvertical-rl
inline-sizewidthwidthheight
block-sizeheightheightwidth
margin-inline-startmargin-leftmargin-rightmargin-top
margin-inline-endmargin-rightmargin-leftmargin-bottom
margin-block-startmargin-topmargin-topmargin-right
padding-inline-startpadding-leftpadding-rightpadding-top
border-inline-endborder-rightborder-leftborder-bottom
inset-inline-startleftrighttop

Writing Systems and Their CSS Settings

Different writing traditions require specific CSS configurations:

Script / Languagewriting-modedirectiontext-orientation
Latin (English, etc.)horizontal-tbltrmixed
Arabic, Persian, Urduhorizontal-tbrtlmixed
Hebrew, Yiddishhorizontal-tbrtlmixed
Traditional Chinesevertical-rlltrmixed
Japanese (tategumi)vertical-rlltrmixed
Mongolianvertical-lrltrmixed
Devanagari (Hindi)horizontal-tbltrmixed
Korean (modern)horizontal-tbltrmixed

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.

Related Tools

More CSS Tools