Web Platform · CSS Layout
Writing Modes and Logical Properties
How writing-mode rotates the inline and block axes, what direction changes about line layout, and why logical properties resolve against a different rectangle than their physical counterparts.
Every layout concept described so far has been named in physical terms: width, height, top, left. Those names are conveniences that hold only for horizontal text running left to right. The CSS model underneath is flow-relative: boxes have an inline axis along which text advances and a block axis along which lines and blocks stack, and writing-mode and direction determine which physical direction each axis points.
A stylesheet that mixes the two vocabularies produces layouts that break when the writing mode changes. That failure is easy to miss, because the default mode is horizontal top-to-bottom so both vocabularies agree in most testing.
Rotating the axes
writing-mode accepts horizontal-tb, vertical-rl, and vertical-lr. horizontal-tb sets the inline axis horizontally left-to-right (subject to direction) and the block axis top-to-bottom. vertical-rl sets the inline axis vertically top-to-bottom and the block axis right-to-left, so lines stack from the right edge toward the left, which is the traditional layout for Japanese and Chinese text. vertical-lr stacks lines left-to-right, used for Mongolian script.
text-orientation then controls how glyphs sit within vertical lines: mixed rotates Latin text runs sideways while keeping CJK glyphs upright, upright keeps all glyphs upright, and sideways rotates everything. The property has no effect in horizontal writing modes.
The consequence for layout is that “width” and “height” no longer describe the direction in which content flows. A width: 20rem box in vertical-rl is 20rem along the block axis, because the physical horizontal direction is the block direction there; the text advances vertically. Any rule that sizes boxes based on the assumption that text runs horizontally needs re-examination.
The block and inline axes are also what flex-direction: row and grid-template-columns follow. In a vertical writing mode, row lays items out vertically. This is deliberate: the layout modes are defined in flow-relative terms, so a grid that was designed for a horizontal mode becomes a transposed grid in a vertical one. For interfaces that must support both, the properties have to be chosen with the axis mapping in mind rather than the visual result in one mode.
direction and bidirectional text
direction takes ltr or rtl and sets the base direction for the inline axis. It affects the ordering of inline-level boxes, the default alignment of text, the side on which list markers appear, and which physical side counts as the inline start and end. It does not touch the block axis: block-start and block-end come from writing-mode alone.
The property does not reverse the order of characters within a word. Character ordering within a run is decided by the Unicode Bidirectional Algorithm, which assigns each character a bidirectional class and resolves runs whose direction differs from the paragraph’s base direction. Inline layout then places the resulting runs into line boxes. Arabic and Hebrew words are stored in logical order and displayed in visual order by the algorithm; direction: rtl on a container sets the paragraph embedding level that the algorithm starts from.
Two implications follow for layout. First, direction is inherited and affects more than alignment; a container that sets it changes marker placement and inline box order for all descendants. Second, the unicode-bidi property controls how the algorithm treats an element’s content relative to its surroundings, with values such as isolate and bidi-override. Isolating embedded content prevents a direction change from leaking across element boundaries.
text-align: start and text-align: end follow the inline axis and therefore flip with direction, while left and right do not. The same distinction applies to float: inline-start and float: inline-end, and to the inset properties described below.
The logical property families
Logical properties name box edges relative to the flow rather than the page. The families are:
- Sizing:
inline-sizeandblock-size, withmin-inline-size,max-block-size, and the other combinations. - Margins and padding:
margin-inline-start,margin-inline-end,margin-block-start,margin-block-end, plus the two-value shorthandsmargin-inline(start, end) andmargin-block(start, end). - Borders:
border-inline-start-widthand the other per-edge properties;border-inlinesets both inline edges,border-blockboth block edges. - Positioning:
inset-inline-start,inset-inline-end,inset-block-start,inset-block-end, withinset-inlineandinset-blockshorthands. - Corner radii: properties such as
border-start-start-radius, naming the corner by the two edges that meet there.
For a horizontal left-to-right box, inline-start maps to left, inline-end to right, block-start to top, block-end to bottom. In vertical-rl, inline-start maps to top and block-start to right. In a right-to-left horizontal box, inline-start maps to right and block-start stays top.
The mapping is resolved at used-value time from the element’s own writing mode, direction, and text-orientation, not from a global setting. A child element can change writing-mode, and its own logical properties then map differently from its parent’s.
/* Physical: breaks when the writing mode rotates. */
.legacy {
padding-left: 1rem;
border-left: 2px solid currentColor;
}
/* Logical: the border follows the inline start edge in any mode. */
.modern {
padding-inline-start: 1rem;
border-inline-start: 2px solid currentColor;
inline-size: 20rem;
margin-block: 1rem 2rem;
}
The two-value form of margin-inline: 1rem 2rem assigns 1rem to the start edge and 2rem to the end edge. There is no four-value logical shorthand for margins, because the two axes are independent; the four physical edges require combining margin-inline and margin-block.
Percentages and the containing block under rotation
Percentage resolution uses the containing block’s inline and block sizes, which are physical dimensions chosen by the containing block’s writing mode. inline-size: 50% resolves against the containing block’s inline size, which is its width in a horizontal mode and its height in a vertical one.
Padding percentages are the exception that catches people who assume the logic extends to every property. All four padding percentages, physical or logical, resolve against the containing block’s inline size, as described in used values for the box model. A padding-block-start: 10% in a horizontal mode therefore depends on the containing block’s width, and in a vertical mode it depends on the containing block’s height, because the height is the inline size there. The logical name changes which edge receives the value but not the rectangle the percentage measures against. Margins follow the same rule. Sizing properties are not affected by it: block-size: 50% does resolve against the containing block’s block size, which is its height in a horizontal mode.
A rotated box also changes which side scrollbars appear on and which direction overflow: auto scrolls. The scroll origin follows the inline and block axes: in vertical-rl, content that overflows in the inline direction scrolls from top to bottom, and the initial scroll position is at the block start, which is the right edge.
Orthogonal flows
A box whose writing-mode differs from its containing block’s is an orthogonal flow. The classic case is a horizontal toolbar inside a vertical document, or a vertical caption inside a horizontal card. Orthogonal boxes still participate in their parent’s inline formatting, but the two axes are swapped, so a percentage on the child’s inline axis resolves against the parent’s block axis.
The specification resolves the resulting ambiguity by treating the child’s dimensions as definite where possible and falling back to intrinsic sizes otherwise. Sizing an orthogonal child with a percentage of the parent’s block size is generally safe when the parent has a definite block size and unreliable when it does not, because the cycle is broken by treating the percentage as auto.
Orthogonal flows also interact with scroll containers: a scroll container’s scrollbar is placed according to the scroll container’s own writing mode, not its content’s. A horizontally scrolling strip inside a vertical page uses the horizontal scrollbar of the strip’s own axis, which is why the writing-mode of the scroll container matters as much as the direction of the overflow.
Logical properties are the practical answer to most of these cases. Writing every box edge in flow-relative terms means the same rule set survives a change of writing mode, a change of direction, or a component reused in a layout with different axes. The properties that remain physical, such as top or left, should be reserved for cases where the physical side is genuinely what is meant, such as a visually anchored corner decoration.
References
- CSS Writing Modes Level 3 — W3C
- CSS Logical Properties and Values Level 1 — W3C
- Unicode Standard Annex #9: Unicode Bidirectional Algorithm — Unicode Consortium