- Published on
Mastering CSS Writing Mode: A Comprehensive Guide for Modern Web Layouts
- Authors
- Name
- Md Nasim Sheikh
- @nasimStg
'Mastering CSS Writing Mode: A Comprehensive Guide for Modern Web Layouts'
Go beyond horizontal layouts and discover the power of CSS writing-mode
. This guide covers everything from vertical text to logical properties for creating truly global and creative web designs.
Table of Contents
- 'Mastering CSS Writing Mode: A Comprehensive Guide for Modern Web Layouts'
- What Exactly is writing-mode?
- The Core Values of writing-mode
- 1. horizontal-tb (The Default)
- 2. vertical-rl
- 3. vertical-lr
- The Game Changer: Logical Properties vs. Physical Properties
- A Practical Comparison
- Practical Use Cases & Creative Layouts
- 1. Vertical Navigation Tabs
- 2. Space-Saving Table Headers
- 3. Creative Typographic Posters
- Fine-Tuning: Interactions with Other CSS Properties
- text-orientation
- Flexbox and Grid
- Best Practices and Accessibility
- Conclusion
Have you ever wanted to break free from the standard top-to-bottom, left-to-right flow of the web? Maybe you've needed to design a layout for a language that's written vertically, like Japanese, or you just wanted to add a splash of typographic creativity with vertical text on a poster or navigation bar. For years, achieving this was a clunky affair involving CSS transforms and positioning hacks. But not anymore.
Meet writing-mode
, a powerful CSS property that fundamentally changes how text and layout flow on a page. It’s not just a text-rotation tool; it’s a gateway to building more flexible, accessible, and internationally-aware websites. In this guide, we'll take a deep dive into writing-mode
, exploring everything from the basics to advanced interactions with Flexbox, Grid, and the revolutionary concept of logical properties.
Get ready to change your perspective—literally.
writing-mode
?
What Exactly is At its core, the writing-mode
property defines the direction in which text lines are laid out (the inline direction) and the direction in which new lines and blocks are stacked (the block direction).
To truly grasp this, we need to understand two fundamental concepts:
- Inline Base Direction: This is the direction words and letters flow in a line. For English, it's left-to-right. For Arabic, it's right-to-left.
- Block Flow Direction: This is the direction in which new block-level elements (like paragraphs
<p>
or divs<div>
) are stacked. For a standard English webpage, the block flow direction is top-to-bottom.
Think of a book. In an English book, you read letters from left-to-right (inline direction), and when you finish a line, you move down the page (block direction). writing-mode
gives you control over both of these axes.
writing-mode
The Core Values of The writing-mode
property accepts three main values that dictate the layout flow. Let's break them down.
horizontal-tb
(The Default)
1. This is the writing mode you've been using all along, whether you knew it or not. It's the default value for content on the web.
horizontal
: The inline base direction is horizontal.tb
: The block flow direction is top-to-bottom.
.element {
writing-mode: horizontal-tb;
}
All text flows horizontally, and block elements like paragraphs stack vertically from the top of the container to the bottom. Simple.
vertical-rl
2. This is where things get interesting. vertical-rl
is essential for many East Asian languages like Chinese, Japanese, and Korean.
vertical
: The inline base direction is vertical. Text flows from top to bottom.rl
: The block flow direction is right-to-left. New vertical lines of text (and other blocks) are added to the left of the previous one.
Imagine a traditional Japanese newspaper. You start reading at the top-right of the page, read down the column, and then move to the next column to the left.
Example:
Let's apply this to a simple div
:
<div class="vertical-rl-example">
<h3>Vertical Title</h3>
<p>This is a paragraph of text that will flow vertically from top to bottom. New lines will stack from right to left, creating a unique layout.</p>
<p>This is a second paragraph. It will appear to the left of the first one.</p>
</div>
.vertical-rl-example {
writing-mode: vertical-rl;
border: 2px solid #4a90e2;
padding: 1rem;
width: 400px; /* Note the effect on width/height */
height: 250px;
}
.vertical-rl-example h3 {
border-left: 3px solid #d0021b;
padding-left: 0.5rem;
}
In a browser, this will render with the <h3>
as the rightmost block, and the two paragraphs following it to its left. The text within each element will read from top to bottom.
vertical-lr
3. This is similar to vertical-rl
but changes the block flow direction.
vertical
: The inline base direction is still vertical (top-to-bottom).lr
: The block flow direction is left-to-right. New vertical lines and blocks are added to the right of the previous one.
This mode is used for languages like Mongolian.
Example:
.vertical-lr-example {
writing-mode: vertical-lr;
border: 2px solid #4a90e2;
padding: 1rem;
width: 400px;
height: 250px;
}
Using the same HTML as before, the <h3>
would now be the leftmost block, with the subsequent paragraphs appearing to its right.
A Note on Deprecated Values: You might see
sideways-rl
andsideways-lr
in older articles. These have been deprecated. Their goal was to lay out text as if you'd physically rotated ahorizontal-tb
line of text. This functionality is now better handled by thetext-orientation
property, which we'll discuss later.
The Game Changer: Logical Properties vs. Physical Properties
This is the most critical concept to master when working with writing-mode
. For years, we've used physical properties to define size and space. Properties like width
, height
, margin-top
, and padding-left
are tied to the physical dimensions of the screen (top, right, bottom, left).
When you change the writing-mode
, these physical properties don't adapt. A width
is always a horizontal measurement, and a height
is always vertical. This can lead to chaos in a vertical layout.
Enter Logical Properties.
Logical properties are direction-agnostic. Instead of top
or left
, they use concepts like block-start
and inline-end
. Their physical meaning changes based on the element's writing-mode
.
Here’s a quick mapping:
Physical Property | Logical Property | Description in horizontal-tb | Description in vertical-rl |
---|---|---|---|
width | inline-size | Horizontal size | Vertical size |
height | block-size | Vertical size | Horizontal size |
margin-top | margin-block-start | Margin at the top | Margin at the right |
margin-bottom | margin-block-end | Margin at the bottom | Margin at the left |
margin-left | margin-inline-start | Margin at the left | Margin at the top |
margin-right | margin-inline-end | Margin at the right | Margin at the bottom |
padding-top | padding-block-start | Padding at the top | Padding at the right |
padding-bottom | padding-block-end | Padding at the bottom | Padding at the left |
padding-left | padding-inline-start | Padding at the left | Padding at the top |
padding-right | padding-inline-end | Padding at the right | Padding at the bottom |
border-left | border-inline-start | Border on the left | Border on the top |
There are also shorthand properties like margin-block
(for margin-block-start
and margin-block-end
) and margin-inline
(for margin-inline-start
and margin-inline-end
).
A Practical Comparison
Let's see why this matters. Here's a card styled with physical properties.
<div class="card physical-card">
<h4>Physical Properties</h4>
<p>This card uses width, height, and margin-top. It will break in vertical mode.</p>
</div>
/* The Problem: Physical Properties */
.physical-card {
width: 300px;
height: 150px;
margin-top: 20px;
padding-left: 15px;
border-left: 5px solid red;
background: #f0f0f0;
}
/* Now let's switch the writing mode on a container */
.container-vertical {
writing-mode: vertical-rl;
}
If you place this card inside .container-vertical
, the width
will still try to control the horizontal dimension, and height
the vertical one. The margin-top
will still add space above it, and the border-left
will remain on the physical left. The result is a squished, unusable component.
Now, let's refactor it with logical properties.
<div class="card logical-card">
<h4>Logical Properties</h4>
<p>This card uses inline-size, block-size, and margin-block-start. It adapts perfectly!</p>
</div>
/* The Solution: Logical Properties */
.logical-card {
inline-size: 300px; /* Was width */
block-size: 150px; /* Was height */
margin-block-start: 20px; /* Was margin-top */
padding-inline-start: 15px; /* Was padding-left */
border-inline-start: 5px solid green; /* Was border-left */
background: #e6f7ff;
}
When you place this card inside the .container-vertical
, magic happens:
inline-size: 300px
now controls the vertical height (the new inline direction).block-size: 150px
now controls the horizontal width (the new block direction).margin-block-start: 20px
adds a margin to the right (the start of the block flow).border-inline-start: 5px
adds a border to the top (the start of the inline flow).
The component reorients itself perfectly without a single media query or JavaScript intervention. This is the future of resilient, multi-directional web design.
Practical Use Cases & Creative Layouts
Now for the fun part! Let's see where writing-mode
shines.
1. Vertical Navigation Tabs
This is a classic UI pattern. Instead of using transforms, we can use writing-mode
for a cleaner implementation.
<nav class="vertical-tabs">
<a href="#" class="active">Dashboard</a>
<a href="#">Profile</a>
<a href="#">Messages</a>
<a href="#">Settings</a>
</nav>
.vertical-tabs {
display: flex;
flex-direction: column; /* Stack tabs vertically */
width: 150px;
}
.vertical-tabs a {
writing-mode: vertical-rl;
text-orientation: sideways; /* We'll cover this next! */
background: #eee;
padding: 1rem;
border-bottom: 1px solid #ccc;
text-align: center;
transform: rotate(180deg); /* Re-orient the sideways text to read top-to-bottom */
}
.vertical-tabs a.active {
background: #4a90e2;
color: white;
}
Wait, what's with text-orientation
and transform
? We're getting a little ahead, but in short: writing-mode
makes the line vertical, text-orientation: sideways
turns the letters on their side, and transform: rotate(180deg)
flips the whole block so the text reads downwards instead of upwards. We'll clarify this in the next section.
2. Space-Saving Table Headers
Got a table with many columns? Vertical headers can make it fit in a smaller space.
<table>
<thead>
<tr>
<th class="vertical-header"><span>Item ID</span></th>
<th class="vertical-header"><span>Customer Name</span></th>
<th class="vertical-header"><span>Order Date</span></th>
</tr>
</thead>
<tbody>
<tr>
<td>101</td>
<td>John Doe</td>
<td>2023-10-27</td>
</tr>
</tbody>
</table>
.vertical-header {
writing-mode: vertical-rl;
text-orientation: sideways;
transform: rotate(180deg);
text-align: left; /* Aligns text to the 'bottom' of the cell */
white-space: nowrap;
padding: 10px 5px;
vertical-align: bottom;
}
This technique dramatically reduces the width required for your table headers.
3. Creative Typographic Posters
writing-mode
is a fantastic tool for graphic and web designers looking to create visually striking hero sections or digital posters.
<div class="poster">
<h1 class="main-title">VERTICAL</h1>
<p class="subtitle">A New Perspective</p>
</div>
.poster {
writing-mode: vertical-rl;
height: 500px;
border: 5px solid black;
padding: 2rem;
text-align: center; /* Centers the text along the inline (vertical) axis */
}
.main-title {
font-size: 8rem;
letter-spacing: 1rem; /* Creates space between letters vertically */
text-transform: uppercase;
}
.subtitle {
writing-mode: horizontal-tb; /* You can reset it for inner elements! */
display: inline-block; /* Make it a block for layout */
margin-top: 1rem;
background: black;
color: white;
padding: 0.5rem 1rem;
}
Fine-Tuning: Interactions with Other CSS Properties
writing-mode
doesn't exist in a vacuum. It has profound effects on other CSS layout modules.
text-orientation
This property is the loyal companion to writing-mode: vertical-*
. It controls how characters are oriented within a vertical line.
mixed
(default): This is the standard for East Asian languages. Characters from horizontal-only scripts (like Latin, which we're using) are rotated 90° clockwise. CJK (Chinese, Japanese, Korean) characters remain upright.upright
: Forces all characters to be set upright, one below the other. This can be great for short acronyms or labels (e.g., 'USA').sideways
: Lays out all characters sideways, as if an entire line of horizontal text was rotated 90° clockwise. This is what we used in the vertical tabs example. Note thatsideways
is often more readable for long strings of Latin text thanmixed
.
.element-mixed {
writing-mode: vertical-rl;
text-orientation: mixed; /* Default, 'Hello' is rotated */
}
.element-upright {
writing-mode: vertical-rl;
text-orientation: upright; /* Each letter of 'Hello' is upright */
}
.element-sideways {
writing-mode: vertical-rl;
text-orientation: sideways; /* The word 'Hello' is rotated as a block */
}
Flexbox and Grid
This is where your brain might bend a little. writing-mode
redefines the axes for both Flexbox and Grid.
Flexbox:
The main axis
and cross axis
of a flex container are defined by flex-direction
. But writing-mode
determines what row
and column
actually mean.
- In
horizontal-tb
(default):flex-direction: row
= main axis is horizontal.flex-direction: column
= main axis is vertical.
- In
vertical-rl
:flex-direction: row
= main axis is vertical.flex-direction: column
= main axis is horizontal.
That's right—row
becomes vertical and column
becomes horizontal. The axes follow the flow of the text. justify-content
will always align items along the main axis, and align-items
will always align them on the cross axis, whatever direction those axes may be pointing.
Grid:
Grid layout is similarly affected. The block
and inline
axes, which determine the flow of auto-placed grid items, are swapped. grid-template-rows
will define tracks along the new block direction (horizontally in vertical-rl
), and grid-template-columns
will define tracks along the new inline direction (vertically in vertical-rl
).
Always think in terms of block and inline, not physical directions, and your layouts will be robust.
Best Practices and Accessibility
Embrace Logical Properties: This is the #1 rule. If you're using
writing-mode
, you should be using logical properties for sizing, spacing, and borders. It future-proofs your components.Use the
lang
Attribute: When marking up content in a different language, always use thelang
attribute (e.g.,<html lang="ja">
). This is crucial for accessibility, as it tells screen readers how to correctly pronounce the content.Test Your Fonts: Not all fonts are created equal. Some may not include vertical metrics or may render certain glyphs awkwardly in vertical mode. Test with your chosen web fonts.
Consider Readability: For scripts that aren't natively vertical (like Latin), be mindful of readability.
text-orientation: sideways
is often better for full sentences thanupright
ormixed
. Keep vertical text short and sweet for decorative purposes.Browser Support: Browser support for
writing-mode
and logical properties is excellent across all modern browsers. You can use them with confidence.
Conclusion
CSS writing-mode
is so much more than a party trick for rotating text. It's a fundamental property that unlocks a new dimension of web layout. By shifting our mindset from a fixed, physical coordinate system to a flexible, logical one, we can build components and websites that are more resilient, more creative, and more inclusive of global audiences.
So, the next time you're building a UI, ask yourself: does this have to be horizontal-tb
? You might be surprised by the elegant solutions that emerge when you change your writing mode and start thinking logically.