What Are CSS Writing Modes?
CSS Writing Modes define the primary directions in which text flows and blocks stack on a page. They are a fundamental but often overlooked part of modern CSS layout that control the inline progression (the direction a line of text flows) and the block progression (the direction in which lines stack one after another). The core property is writing-mode, supported by direction and text-orientation.
The writing-mode property accepts the following key values:
horizontal-tb— Text flows horizontally, lines stack from top to bottom. This is the default for languages like English, French, Hindi, and many others.vertical-rl— Text flows vertically, lines stack from right to left. Common for Japanese, Chinese, Korean, and traditional Mongolian.vertical-lr— Text flows vertically, lines stack from left to right. Used in some edge cases or design choices.sideways-rl— Horizontal text is rotated 90° clockwise; lines stack right to left. (Limited browser support, mostly for decorative purposes.)sideways-lr— Horizontal text is rotated 90° counterclockwise; lines stack left to right.
Understanding writing modes unlocks the ability to create layouts that adapt to different language directions and to build vertical content without heavy JavaScript or CSS transforms.
Why Writing Modes Matter
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →CSS Writing Modes are not just for multilingual websites—they are a design superpower. Here’s why you should master them:
- True Internationalization: Arabic, Hebrew, and many other scripts use right‑to‑left horizontal flow; Chinese, Japanese, and Korean frequently use vertical writing. A properly globalized design must respect these modes.
- Native Vertical Layouts: Instead of using
transform: rotate()to create vertical text, writing modes offer native rendering with correct character orientation, glyph handling, and text selection. - Logical Properties Synergy: When you switch
writing-mode, logical properties likemargin-inline-startandpadding-block-endautomatically reorient themselves, keeping your layout intentions intact. - Flexible Components: A navigation sidebar, a book spine, or a poster headline can be built once and then work in both horizontal and vertical contexts simply by changing one CSS property.
- Future‑proof Layouts: Flexbox and Grid respect writing modes when you use logical axes, meaning your designs can flip seamlessly without duplicating media queries.
Getting Started with the writing-mode Property
The writing-mode property is the starting point. It sets both the inline direction (where letters go next) and the block direction (where the next line appears). Below are practical code examples that demonstrate each main value.
Default Horizontal Top-to-Bottom
<div class="horizontal-box">
<p>The quick brown fox jumps over the lazy dog.</p>
</div>
<style>
.horizontal-box {
writing-mode: horizontal-tb;
width: 200px;
border: 1px solid #ccc;
padding: 0.5em;
}
</style>
This is the standard flow. The text runs left-to-right (or right-to-left if direction: rtl is applied), and lines stack downward.
Vertical Right-to-Left (Classical East Asian)
<div class="vertical-rl-box">
<p>TEXT TEXT</p>
</div>
<style>
.vertical-rl-box {
writing-mode: vertical-rl;
height: 200px; /* block dimension is now vertical */
width: auto; /* inline dimension becomes horizontal */
border: 1px solid #ccc;
padding: 0.5em;
font-family: 'Noto Serif JP', serif;
}
</style>
Here text flows top‑to‑bottom within each line, and the lines stack from right to left. Notice we use height to constrain the block axis (now vertical) rather than width.
Vertical Left-to-Right
<div class="vertical-lr-box">
<p>Vertical text, lines stack left to right.</p>
</div>
<style>
.vertical-lr-box {
writing-mode: vertical-lr;
height: 150px;
border: 1px solid #ccc;
padding: 0.5em;
}
</style>
This mode is less common for natural languages but useful for UI elements like vertical tabs or progress indicators where you want the first column on the left.
Controlling Text Orientation with text-orientation
In vertical writing modes, the text-orientation property determines how individual characters are rotated. It applies only when writing-mode is a vertical value.
mixed(default) — Characters that have a vertical alternative are displayed upright; others (like Latin letters) are rotated sideways. This is ideal for mixed‑script vertical content.upright— All characters remain in their upright orientation, but the line direction is still vertical. Great for short labels or monospace‑style vertical code.sideways— All characters are rotated 90° clockwise (invertical-rl) or counterclockwise (invertical-lr), making the entire block look like rotated horizontal text.
Example: Mixed vs Upright
<div class="vert-mixed">
<p>CSS Writing Modes waTEXT</p>
</div>
<div class="vert-upright">
<p>CSS Writing Modes waTEXT</p>
</div>
<style>
.vert-mixed {
writing-mode: vertical-rl;
text-orientation: mixed;
height: 150px;
}
.vert-upright {
writing-mode: vertical-rl;
text-orientation: upright;
height: 150px;
}
</style>
With mixed, the Latin letters "CSS Writing Modes" rotate sideways while the Japanese characters stay upright. With upright, everything stands upright—Latin letters appear one below the other, which is often used for narrow UI elements.
Embracing Logical Properties for Robust Layouts
Physical properties like margin-left, width, or border-right are tied to the physical screen. When writing-mode changes, their meaning can become counterintuitive. Logical properties describe dimensions relative to the flow: inline (along the text flow) and block (perpendicular to the flow).
Key logical properties include:
inline-size/block-size— analogous towidth/heightbut adapt to writing mode.margin-inline-start/margin-inline-end— spacing before/after the text flow.margin-block-start/margin-block-end— spacing before/after the block direction.padding-inline-*,border-inline-*, etc.
Example: A Card That Works in Any Writing Mode
<div class="card">
<h3>Article Title</h3>
<p>This is a short description that should flow correctly regardless of writing mode.</p>
</div>
<style>
.card {
/* Logical dimensions */
inline-size: 250px;
block-size: auto;
/* Logical margins */
margin-block-end: 1rem;
/* Logical padding */
padding-inline: 1rem;
padding-block: 1rem;
border-inline-start: 4px solid tomato;
background: #fafafa;
}
</style>
If you later add writing-mode: vertical-rl to the .card or to a parent, the inline-size automatically constrains the horizontal dimension (now the inline axis), and the thick border moves to the top (since inline‑start becomes top in vertical‑rl). No manual adjustments needed.
Practical Layout Examples
Vertical Navigation Sidebar
A common pattern is a sidebar where each menu item is rotated vertically. Instead of CSS transforms, writing modes keep text selection natural and allow flexible sizing.
<nav class="vert-nav">
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Services</a>
<a href="#">Contact</a>
</nav>
<style>
.vert-nav {
writing-mode: vertical-rl;
text-orientation: mixed; /* keeps Latin letters rotated */
block-size: 100vh; /* full height */
display: flex;
flex-direction: column;
align-items: center;
gap: 1rem;
padding-block: 1rem;
background: #2c3e50;
}
.vert-nav a {
color: white;
text-decoration: none;
padding-inline: 0.5em;
border-block-end: 2px solid transparent;
}
.vert-nav a:hover {
border-block-end-color: #e67e22;
}
</style>
The navigation links stack vertically, the text inside them flows top‑to‑bottom, and the hover underline appears on the block‑end side (which in this mode is the bottom of the line). Screen readers and search engines still read the text as "Home" etc.
Vertical Headings in a Horizontal Article
<article>
<h2 class="vert-heading">Introduction</h2>
<p>This paragraph flows horizontally as normal.</p>
</article>
<style>
.vert-heading {
writing-mode: vertical-lr;
text-orientation: upright;
float: left; /* classic float to wrap text around */
margin-inline-end: 1rem;
border-inline-end: 2px solid #333;
padding-inline-end: 0.5rem;
font-size: 2rem;
}
</style>
The heading sits to the left, its letters upright one below the other, while the paragraph text wraps around it. Logical margins ensure spacing adjusts if you ever flip the whole document.
Full Vertical Page (Like a Traditional Book)
<div class="vertical-page">
<header>TEXT1chapter: TEXTnoTEXT</header>
<section>
<p>Once upon a time、TEXT…</p>
<p>TEXTnoTEXTwaTEXT。</p>
</section>
</div>
<style>
.vertical-page {
writing-mode: vertical-rl;
text-orientation: mixed;
inline-size: 100%; /* horizontal becomes inline axis */
block-size: 100vh; /* vertical becomes block axis */
overflow-y: auto; /* scroll horizontally? Actually overflow becomes overflow-inline */
column-width: 15em; /* columns now stack horizontally */
column-gap: 2em;
padding-inline: 1em;
}
.vertical-page header {
font-weight: bold;
border-block-end: 1px solid #aaa;
margin-block-end: 1em;
}
</style>
This creates a paginated vertical layout with columns that flow right‑to‑left, resembling a Japanese novel. The column-width property works in the inline direction, so it automatically creates horizontal columns.
Best Practices and Tips
-
Start with logical properties: Whenever possible, replace
widthwithinline-size,heightwithblock-size, and usemargin-inline/padding-inline. This makes your components reusable across all writing modes. -
Use
text-orientation: mixedas default for vertical text: It handles mixed scripts gracefully. Reserveuprightfor narrow UI labels or when you need every character upright. - Test with real content: Always load actual text in the target languages. Not all fonts support vertical alternates; use fonts like Noto Serif JP or Source Han Serif for CJK content.
-
Don't mix physical and logical properties in the same layout: For example, avoid setting
width: 200pxand thenmargin-block-start. Stick to one system to avoid confusion when the mode changes. -
Consider the containing block: When you change
writing-modeon a container, all children inherit the new flow. If a child needs to stay horizontal, setwriting-mode: horizontal-tbexplicitly on that child. -
Use with Flexbox and Grid intelligently: Flexbox’s
flex-directionfollows the writing mode. For example,flex-direction: columnin a vertical‑rl context makes items flow horizontally. Use logical values likeflex-direction: column(block axis) orflex-direction: row(inline axis) with awareness of the mode. -
Manage overflow carefully: In vertical modes, the block axis is vertical, so
overflow-ystill refers to vertical scrolling. But the inline axis becomes horizontal, sooverflow-xscrolls horizontally. Use logical overflow properties if available (overflow-block,overflow-inline), but browser support is still evolving—fall back to physical ones with testing. - Accessibility: Screen readers generally handle writing modes well, but always test that the reading order matches the visual order. Use ARIA attributes sparingly and rely on the DOM order and CSS flow.
Common Pitfalls and How to Avoid Them
-
Text suddenly overflows horizontally: In vertical modes, the inline axis is horizontal. If you set a fixed
heightbut forget thatwidthis now the block size, you might get unexpected clipping. Fix: useinline-sizeto constrain the text flow direction. -
Directional icons or arrows look wrong: Icons like ▶ or ▶ may not rotate as expected. Use
text-orientationor replace them with CSS‑based arrows that respect the flow. -
Scroll direction feels reversed: In
vertical-rl, the natural reading order starts from the right. Users may expect to scroll horizontally from right to left. Test with actual users and considerdirection: rtlon the container if needed. -
Nested tables or forms break: Form controls and table cells have their own internal layout. Apply
writing-modecarefully and reset it for certain controls if they need horizontal input. -
Font metrics cause uneven line heights: Vertical text often requires adjusting
line-heightorletter-spacing. Experiment with values likeline-height: 1.8for vertical CJK text to improve readability.
Conclusion
Mastering CSS Writing Modes opens a world of expressive, culturally aware, and maintainable layouts. By shifting from physical dimensions to logical properties and embracing the writing-mode property, you can create components that gracefully adapt to horizontal and vertical flows, right‑to‑left or left‑to‑right languages. Start small—add vertical headings or a sidebar—and gradually adopt logical sizing everywhere. The result is a codebase that respects the diversity of language and design without fragile workarounds. Experiment with the examples above, test with real multilingual content, and let your layouts flow naturally in every direction.