CSS Writing Modes Module Level 3
CSS Writing Modes Module Level 3
Editor’s Draft
18 January 2026
More details about this document
This version:
Latest published version:
Previous Versions:
Test Suite:
Feedback:
CSSWG Issues Repository
Tracker
Editors:
Elika J. Etemad / fantasai
Apple
Koji Ishii
Google
Former Editors:
Shinyu Murakami
Antenna House
Paul Nelson
Microsoft
Michel Suignard
Microsoft
Suggest an Edit for this Spec:
GitHub Editor
World Wide Web Consortium
W3C
liability
trademark
and
permissive document license
rules apply.
Abstract
CSS Writing Modes Level 3 defines CSS support for various writing modes and their combinations, including left-to-right and right-to-left text ordering as well as horizontal and vertical orientations.
CSS
is a language for describing the rendering of structured documents
(such as HTML and XML)
on screen, on paper, etc.
Status of this document
This is a public copy of the editors’ draft.
It is provided for discussion only and may change at any moment.
Its publication here does not imply endorsement of its contents by W3C.
Don’t cite this document other than as work in progress.
Please send feedback
by
filing issues in GitHub
(preferred),
including the spec code “css-writing-modes” in the title, like this:
“[css-writing-modes]
…summary of comment…
”.
All issues and comments are
archived
Alternately, feedback can be sent to the (
archived
) public mailing list
www-style@w3.org
This document is governed by the
18 August 2025 W3C Process Document
Candidate corrections
are marked in the document.
1.
Introduction to Writing Modes
CSS Writing Modes Level 3 defines CSS features to support for various international
writing modes, such as left-to-right (e.g. Latin or Indic), right-to-left
(e.g. Hebrew or Arabic), bidirectional (e.g. mixed Latin and Arabic) and
vertical (e.g. Asian scripts).
writing mode
in CSS is determined by the
writing-mode
direction
, and
text-orientation
properties. It is defined primarily
in terms of its
inline base direction
and
block flow direction
Latin-based writing mode
Mongolian-based writing mode
Han-based writing modes
The
inline base direction
is the primary direction in which
content is ordered on a line and defines on which sides the “start”
and “end” of a line are. The
direction
property specifies the
inline base direction of a box and, together with the
unicode-bidi
property and the inherent directionality of any text content, determines
the ordering of inline-level content within a line.
The
block flow direction
is the direction in which
block-level boxes stack and the direction in which line boxes stack
within a block container. The
writing-mode
property determines the
block flow direction.
Writing systems typically have one or two native writing modes. Some
examples are:
Latin-based systems are typically written using a left-to-right inline
direction with a downward (top-to-bottom) block flow direction.
Arabic-based systems are typically written using a right-to-left
inline direction with a downward (top-to-bottom) block flow direction.
Mongolian-based systems are typically written using a top-to-bottom
inline direction with a rightward (left-to-right) block flow direction.
Han-based systems are commonly written using a left-to-right inline direction
with a downward (top-to-bottom) block flow direction,
or
a top-to-bottom inline direction with a leftward (right-to-left) block
flow direction. Many magazines and newspapers will mix these two writing
modes on the same page.
horizontal writing mode
is one with horizontal lines of text,
i.e. a downward or upward block flow.
vertical writing mode
is one with vertical lines of text,
i.e. a leftward or rightward block flow.
These terms should not be confused with
vertical block flow
(which is a downward or upward block flow)
and
horizontal block flow
(which is leftward or rightward block flow).
To avoid confusion, CSS specifications avoid this latter set of terms.
The
typographic mode
determines whether to use
typographic conventions specific to vertical flow for
vertical scripts
vertical typographic mode
or to use the typographic conventions of
horizontal writing modes
horizontal typographic mode
).
This concept distinguishes vertical typesetting
from rotated horizontal typesetting.
The
text-orientation
component of the writing mode
controls the
glyph orientation
in
vertical typographic modes
dictating whether a particular
typographic character unit
is
typeset upright
or
typeset sideways
See Unicode Technical Note #22
[UTN22]
HTML version
for a more in-depth introduction to writing modes and vertical text.
1.1.
Module Interactions
This module replaces and extends the
unicode-bidi
and
direction
features defined in
[CSS2]
sections 8.6 and 9.10.
The interaction of its features
with other text operations
in setting lines of text
is described in
CSS Text 3
§ A Text Processing Order of Operations
The
computed values
of the
writing-mode
direction
, and
text-orientation
properties
(even on elements to which these properties themselves don’t apply
[CSS-CASCADE-4]
are broadly able to influence the computed values of other, unrelated properties
through calculations such as
the computation of
font-relative lengths
or the cascade of
flow-relative properties
which purposefully depend on the computed
writing mode
or on font metrics that can depend on the
writing mode
1.2.
Value Definitions and Terminology
This specification follows the
CSS property definition conventions
from
[CSS2]
using the
value definition syntax
from
[CSS-VALUES-3]
Value types not defined in this specification are defined in CSS Values & Units
[CSS-VALUES-3]
Combination with other CSS modules may expand the definitions of these value types.
In addition to the property-specific values listed in their definitions,
all properties defined in this specification
also accept the
CSS-wide keywords
as their property value.
For readability they have not been repeated explicitly.
Other important terminology and concepts used in this specification
are defined in
[CSS2]
and
[CSS-TEXT-3]
2.
Inline Direction and Bidirectionality
While the characters in most scripts are written from left to right,
certain scripts are written from right to left. In some documents,
in particular those written with the Arabic or Hebrew script, and in
some mixed-language contexts, text in a single (visually displayed)
block may appear with mixed directionality. This phenomenon is called
bidirectionality
, or "bidi" for short.
Bidirectionality
The Unicode standard (
Unicode Standard Annex #9
) defines a complex
algorithm for determining the proper ordering of bidirectional text. The
algorithm consists of an implicit part based on character properties,
as well as explicit controls for embeddings and overrides. CSS relies
on this algorithm to achieve proper bidirectional rendering.
Two CSS properties,
direction
and
unicode-bidi
provide explicit embedding, isolation, and override controls in the CSS layer.
Because the base directionality of a text depends on the structure and
semantics of the document, the
direction
and
unicode-bidi
properties
should in most cases be used only to map bidi information in the markup
to its corresponding CSS styles.
The HTML specifications (
[HTML401]
, section 8.2, and
HTML
§ 15.3.5 Bidirectional text
) define
bidirectionality behavior for HTML elements.
If a document language provides markup features to control
bidi, authors and users should use those features instead
and not specify CSS rules to override them.
2.1.
Specifying Directionality: the
direction
property
Name:
direction
Value:
ltr
rtl
Initial:
ltr
Applies to:
all elements
Inherited:
yes
Percentages:
n/a
Computed value:
specified value
Canonical order:
n/a
Animation type:
not animatable
Because HTML UAs can turn off CSS styling,
we recommend HTML authors to use the HTML
dir
attribute and element
to ensure correct bidirectional layout in the absence of a style sheet.
Authors
should not
use
direction
in HTML documents.
This property specifies the
inline base direction
or directionality
of any bidi paragraph, embedding, isolate, or override established by the box.
(See
unicode-bidi
.)
In addition, it informs the ordering of
table
column layout,
the direction of horizontal
overflow
and the default alignment of text within a line, and other layout effects
that depend on the box’s inline base direction.
Values for this property have the following meanings:
ltr
This value sets
inline base direction
(bidi directionality)
to
line-left
-to-
line-right
rtl
This value sets
inline base direction
(bidi directionality)
to
line-right
-to-
line-left
The
direction
property has no effect on bidi reordering
when specified on inline boxes whose
unicode-bidi
value is
normal
because the box does not open an additional level
of embedding with respect to the bidirectional algorithm.
The
direction
property, when specified for table column boxes, is not inherited by
cells in the column since columns are not the ancestors of the cells in
the document tree. Thus, CSS cannot easily capture the "dir" attribute
inheritance rules described in
[HTML401]
, section 11.3.2.1.
2.2.
Embeddings and Overrides: the
unicode-bidi
property
Name:
unicode-bidi
Value:
normal
embed
isolate
bidi-override
isolate-override
plaintext
Initial:
normal
Applies to:
all elements, but see prose
Inherited:
no
Percentages:
n/a
Computed value:
specified value
Canonical order:
per grammar
Animation type:
not animatable
Because HTML UAs can turn off CSS styling,
we recommend HTML authors to use the HTML
dir
attribute, element,
and appropriate distinction of text-level vs. grouping-level HTML element types
to ensure correct bidirectional layout in the absence of a style sheet.
Authors
should not
use
unicode-bidi
in HTML documents.
Normally (i.e. when
unicode-bidi
is
normal
an inline box is transparent to the unicode bidi algorithm;
content is ordered as if the box’s boundaries were not there.
Other values of the
unicode-bidi
property cause inline boxes
to create scopes within the algorithm,
and to override the intrinsic directionality of text.
The following informative table summarizes the box-internal and
box-external effects of
unicode-bidi
Effect of non-
normal
values of
unicode-bidi
on inline boxes
Outside
strong
neutral
Inside
scoped
embed
isolate
override
bidi-override
isolate-override
plaintext
plaintext
Values for this property have the following (normative) meanings:
normal
The box does not open an additional level of embedding with
respect to the bidirectional algorithm. For inline boxes,
implicit reordering works across box boundaries.
embed
If the box is inline, this value creates a
directional embedding
by opening an additional level of embedding with respect to the bidirectional algorithm.
The direction of this embedding level is given by the
direction
property. Inside the box, reordering is done implicitly.
This value has no effect on boxes that are not inline.
isolate
On an inline box, this
bidi-isolates
its contents.
This is similar to a directional embedding (and increases the embedding level accordingly)
except that each sequence of inline-level boxes
uninterrupted by any block boundary or
forced paragraph break
is treated as an
isolated sequence
the content within the sequence is ordered
as if inside an independent paragraph
with the base directionality specified by the box’s
direction
property.
for the purpose of bidi resolution in its containing bidi paragraph,
the sequence is treated as if it were a single Object Replacement Character (U+FFFC).
In effect, neither is the content inside the box bidi-affected
by the content surrounding the box,
nor is the content surrounding the box bidi-affected by the
content or specified directionality of the box.
However,
forced paragraph breaks
within the box still create
a corresponding break in the containing paragraph.
This value has no effect on boxes that are not inline.
bidi-override
This value puts the box’s immediate inline content in a
directional override
For an inline, this means that the box acts like a
directional embedding
in the bidirectional algorithm,
except that reordering within it is strictly in sequence according to the
direction
property; the implicit part of the bidirectional algorithm
is ignored.
For a block container, the override is applied
to an anonymous inline box that surrounds all of its content.
isolate-override
This combines the
isolation
behavior of
isolate
with the
directional override
behavior of
bidi-override
to surrounding content, it is equivalent to
isolate
but within the box content is ordered as if
bidi-override
were specified.
It effectively nests a
directional override
inside an
isolated sequence
plaintext
This value behaves as
isolate
except that for the purposes of
the Unicode bidirectional algorithm, the base directionality of each
of the box’s
bidi paragraphs
(if a block container)
or
isolated sequences
(if an inline)
is determined by following the heuristic in rules P2 and P3
of the Unicode bidirectional algorithm
(rather than by using the
direction
property of the box).
Following Unicode Bidirectional Algorithm clause HL3
[UAX9]
values other than
normal
effectively insert the corresponding Unicode bidi control codes
into the text stream at the start and end of the inline element
before passing the paragraph to the Unicode bidirectional algorithm for reordering.
(See
§ 2.4.2 CSS–Unicode Bidi Control Translation, Text Reordering
.)
Bidi control codes injected by
unicode-bidi
at the start/end of
display: inline
boxes
unicode-bidi
value
direction
value
ltr
rtl
start
end
start
end
normal
embed
LRE (U+202A)
PDF (U+202C)
RLE (U+202B)
PDF (U+202C)
isolate
LRI (U+2066)
PDI (U+2069)
RLI (U+2067)
PDI (U+2069)
bidi-override
LRO (U+202D)
PDF (U+202C)
RLO (U+202E)
PDF (U+202C)
isolate-override
FSI,LRO (U+2068,U+202D)
PDF,PDI (U+202C,U+2069)
FSI,RLO (U+2068,U+202E)
PDF,PDI (U+202C,U+2069)
plaintext
FSI (U+2068)
PDI (U+2069)
FSI (U+2068)
PDI (U+2069)
* The LRO/RLO+PDF pairs are also applied
to the
root inline box
of a
block container
if these values of
unicode-bidi
were specified on the
block container
Because the
unicode-bidi
property does not inherit,
setting
bidi-override
or
plaintext
on a block box will
not affect any descendant blocks. Therefore these values are best
used on blocks and inlines that do not contain any block-level
structures.
Note that
unicode-bidi
does not affect the
direction
property even in the case of
plaintext
, and thus does not affect
direction
-dependent layout calculations.
Because the Unicode algorithm has a limit of 125 levels of embedding,
care should be taken not to overuse
unicode-bidi
values other than
normal
In particular, a value of
inherit
should be used with extreme caution in deeply nested inline markup.
However, for elements that are,
in general, intended to be displayed as blocks, a setting of
unicode-bidi: isolate
is preferred to keep the element together
in case the
display
is changed to
inline
(see example below).
2.3.
Example of Bidirectional Text
The following example shows an XML document with bidirectional
text. It illustrates an important design principle: document language
designers should take bidi into account both in the language proper
(elements and attributes) and in any accompanying style sheets. The
style sheets should be designed so that bidi rules are separate from
other style rules, and such rules should not be overridden by other
style sheets so that the document language’s bidi behavior is preserved.
In this example, lowercase letters stand for inherently left-to-right
characters and uppercase letters represent inherently right-to-left
characters. The text stream is shown below in logical backing store order.


HEBREW1 HEBREW2 english3 HEBREW4 HEBREW5
HEBREW6 HEBREW7 HEBREW8


english9 english10 english11 HEBREW12 HEBREW13
english14 english15 english16
english17 HEBREW18 english19 HEBREW20

Since this is arbitrary XML, the style sheet is responsible for
setting the writing direction. This is the style sheet:
/* Rules for bidi */
[dir=rtl] {direction: rtl; unicode-bidi: isolate; }
[dir=ltr] {direction: ltr; unicode-bidi: isolate; }

/* Rules for presentation */
section, para {display: block;}
emphasis {font-weight: bold;}
quote {font-style: italic;}
If the line length is long,
the formatting of this text might look like this:
5WERBEH 4WERBEH english3 2WERBEH 1WERBEH

8WERBEH
7WERBEH
6WERBEH

english9 english10 english11 13WERBEH 12WERBEH

english14 english15 english16

english17
20WERBEH english19 18WERBEH
The first


element is a block with a right-to-left base direction,
the second

element is a block with a left-to-right base direction.
The

s are blocks that inherit the base direction from their parents.
Thus, the first two

s are read starting at the top right,
the final three are read starting at the top left.
The

element is inline-level,
and since its value for
unicode-bidi
is
normal
(the initial value),
it has no effect on the ordering of the text.
The

element, on the other hand,
creates an
isolated sequence
with the given internal directionality.
Note that this causes
HEBREW18
to be to the right of
english19
If lines have to be broken, the same text might format like this:
2WERBEH 1WERBEH
-EH 4WERBEH english3
5WERB

-EH
7WERBEH
6WERBEH
8WERB

english9 english10 en-
glish11 12WERBEH
13WERBEH

english14 english15
english16

english17
18WERBEH
20WERBEH english19
Notice that because
HEBREW18
must be read before
english19
it is on the line above
english19
Just breaking the long line from the earlier formatting would not have worked.
Note also that the first syllable from
english19
might have fit on the previous line,
but hyphenation of left-to-right words in a right-to-left context, and vice versa,
is usually suppressed to avoid having to display a hyphen in the middle of a line.
2.4.
Applying the Bidirectional Reordering Algorithm
User agents that support bidirectional text must apply the Unicode
bidirectional algorithm to every sequence of inline-level boxes uninterrupted
by any block boundary or
bidi type B
forced paragraph break
This sequence forms the
paragraph
unit
in the bidirectional algorithm.
2.4.1.
Bidi Paragraph Embedding Levels
In CSS,
the paragraph embedding level must be set
(following
UAX9 clause HL1
according to the
direction
property of the paragraph’s containing block
rather than by the heuristic given in steps
P2
and
P3
of the Unicode algorithm.
There is, however, one exception:
when the computed
unicode-bidi
of the paragraph’s containing block is
plaintext
the Unicode heuristics in P2 and P3 are used as described in
[UAX9]
without the HL1 override.
2.4.2.
CSS–Unicode Bidi Control Translation, Text Reordering
The final order of characters within each
bidi paragraph
is the
same as if the bidi control codes had been added as described for
unicode-bidi
(above),
markup had been stripped, and the resulting character sequence had
been passed to an implementation of the Unicode bidirectional
algorithm for plain text that produced the same line-breaks as the
styled text.
Note that bidi control codes in the source text are still honored,
and might not correspond to the document tree structure.
This can split inlines or interfere with bidi start/end control pairing
in interesting ways.
2.4.3.
Bidi Treatment of Atomic Inlines
In this process,
replaced elements
with
display: inline
are treated as neutral characters,
unless their
unicode-bidi
property is either
embed
or
bidi-override
in which case they are treated as strong characters
in the
direction
specified for the element.
(This is so that, in case the replaced element falls back to rendering inlined text content,
its bidi effect on the surrounding text is consistent with its replaced rendering.)
All other atomic inline-level boxes are treated as neutral characters
always.
2.4.4.
Paragraph Breaks Within Embeddings and Isolates
If an inline box is broken around a
bidi paragraph
boundary
(e.g. if split by a block or
forced paragraph break
),
then the
HL3
bidi control codes assigned to the end of the box
are also added before the interruption
and the codes assigned to the start of the box are also added after it.
(In other words, any embedding levels, isolates, or overrides started by the box
are closed at the paragraph break and reopened on the other side of it.)
For example, where
is a
forced paragraph break
the bidi ordering is identical between
......
...
...

and
......
......

for all values of
unicode-bidi
on inline elements and .
Note that this behavior is applied by CSS for CSS-declared bidi controls
applied to the box tree;
it does not apply to Unicode’s bidi formatting controls,
which are defined to terminate their effect at the end of the bidi paragraph.
2.4.5.
Reordering-induced Box Fragmentation
Since bidi reordering can split apart and reorder text
that is logically contiguous,
bidirectional text can cause an
inline box
containing such text
to be split and its fragments reordered within a line.
For each line box, UAs must take the fragments of each inline box
and assign the margins, borders, and padding in visual order (not logical order).
The
start
-most fragment on the first line box in which the box appears
has the
start
edge’s margin, border, and padding;
and the end-most fragment on the last line box in which the box appears
has the
end
edge’s margin, border, and padding.
For example, in the
horizontal-tb
writing mode:
When the parent’s
direction
property is
ltr
the left-most box fragment on the first line box in which the box appears
has the left margin, left border and left padding,
and the right-most box fragment on the last line box in which the box appears
has the right padding, right border and right margin.
When the parent’s
direction
property is
rtl
the right-most fragment of the first line box in which the box appears
has the right padding, right border and right margin,
and the left-most fragment of the last line box in which the box appears
has the left margin, left border and left padding.
Analogous rules hold for vertical writing modes.
The
box-decoration-break
property can override this behavior
to draw box decorations on both sides of each fragment.
[CSS3-BREAK]
3.
Vertical Writing Modes
In addition to extensions to CSS2.1’s support for bidirectional text,
this module introduces the rules and properties needed to support vertical
text layout in CSS.
3.1.
Introduction to Vertical Writing
This subsection is non-normative.
Unlike languages that use the Latin script which are primarily laid out
horizontally, Asian languages such as Chinese and Japanese can be laid out
vertically. The Japanese example below shows the same text laid out
horizontally and vertically. In the horizontal case, text is read
from left to right, top to bottom. For the vertical case, the text is
read top to bottom, right to left.
Indentation from the left edge in the left-to-right horizontal case
translates to indentation from the top edge in the top-to-bottom vertical
case.
Comparison of vertical and horizontal Japanese: iBunko application (iOS)
For Chinese and Japanese lines are ordered either right
to left or top to bottom, while for Mongolian and Manchu lines are
ordered left to right.
The change from horizontal to vertical writing can affect not just the
layout, but also the typesetting. For example, the position of a punctuation
mark within its spacing box can change from the horizontal to the
vertical case, and in some cases alternate glyphs are used.
Vertical text that includes Latin script text or text from other scripts
normally displayed horizontally can display that text in a number of
ways. For example, Latin words can be rotated sideways, or each letter
can be oriented upright:
Examples of Latin in vertical Japanese: Daijirin Viewer 1.4 (iOS)
In some special cases such as two-digit numbers in dates, text is fit
compactly into a single vertical character box:
Mac Fan, December 2010, p.49
Layouts often involve a mixture of vertical and horizontal elements:
Mixture of vertical and horizontal elements
Vertical text layouts also need to handle bidirectional text layout;
clockwise-rotated Arabic, for example, is laid out bottom-to-top.
3.2.
Block Flow Direction: the
writing-mode
property
Name:
writing-mode
Value:
horizontal-tb
vertical-rl
vertical-lr
Initial:
horizontal-tb
Applies to:
All elements except table row groups, table column groups, table rows, table columns, ruby base containers, ruby annotation containers
Inherited:
yes
Percentages:
n/a
Computed value:
specified value
Canonical order:
n/a
Animation type:
not animatable
This property specifies whether lines of text are laid out horizontally
or vertically and the direction in which blocks progress. Possible
values:
horizontal-tb
Top-to-bottom
block flow direction
Both the
writing mode
and the
typographic mode
are horizontal.
vertical-rl
Right-to-left
block flow direction
Both the
writing mode
and the
typographic mode
are vertical.
vertical-lr
Left-to-right
block flow direction
Both the
writing mode
and the
typographic mode
are vertical.
The
writing-mode
property specifies the
block flow direction
which determines the ordering direction of block-level boxes in a block formatting context;
the ordering direction of line boxes in a block container that contains inlines;
the ordering direction of rows in a table; etc.
By virtue of determining the stacking direction of line boxes,
the
writing-mode
property also determines whether the line boxes' orientation (and thus the
writing mode
is horizontal or vertical.
The
text-orientation
property then determines how text is laid out within the line box.
The content of
replaced elements
do not rotate due to the writing mode:
images and external content such as from