Introduction to CSS logical properties
Before we delve into what CSS logical properties are, let’s start with a practical example. Imagine we are creating a simple horizontal list of text messages:
<ul class="horizontal-list"> <li>I am text message no. 1 and I come first in the list</li> <li>I am text message no. 2 and I come second in the list</li> <li>I am text message no. 3 and I come third in the list</li></ul>We use CSS to style the list and each message:
.horizontal-list { list-style: none; white-space: nowrap; padding: 0; margin: 0;
li { white-space: normal; margin-left: 50px; width: 200px; display: inline-block; vertical-align: top; }
li:first-child { margin-left: 0; }}The result is a neatly displayed horizontal list:
- I am text message no. 1 and I come first in the list
- I am text message no. 2 and I come second in the list
- I am text message no. 3 and I come third in the list
Preparing for Globalization
Now, let’s assume the widget becomes so popular that we want to create versions in other languages. While translating to Spanish or French is straightforward, what about Arabic, which is written right-to-left (RTL)? Simply adding a dir="rtl" attribute should address this, but let’s see the outcome:
- I am text message no. 1 and I come first in the list
- I am text message no. 2 and I come second in the list
- I am text message no. 3 and I come third in the list
Notice something odd? There’s no margin between the first and second messages, but there is between the second and third. This occurs because of our margin-left rule, which needs to change to margin-right for RTL languages.
To fix this, we can add an RTL-specific CSS rule:
.horizontal-list { list-style: none; white-space: nowrap; padding: 0; margin: 0;
li { white-space: normal; margin-left: 50px; width: 200px; display: inline-block; vertical-align: top; }
li:first-child { margin-left: 0; }}
[dir='rtl'].horizontal-list { li { margin-left: 0; margin-right: 50px; }
li:first-child { margin-right: 0; }}- I am text message no. 1 and I come first in the list
- I am text message no. 2 and I come second in the list
- I am text message no. 3 and I come third in the list
Now, it looks much better!
Expanding to Other Languages
With the widget’s success, we’re now releasing it in several Asian countries, some of which have scripts that flow top-to-bottom and right-to-left. This means we need to convert margin-left to margin-top and width to height.
Our CSS now includes:
.horizontal-list { list-style: none; white-space: nowrap; padding: 0; margin: 0;
li { white-space: normal; margin-left: 50px; width: 200px; display: inline-block; vertical-align: top; }
li:first-child { margin-left: 0; }}
[dir='rtl'].horizontal-list { li { margin-left: 0; margin-right: 50px; }
li:first-child { margin-right: 0; }}
.vertical-rl.horizontal-list { writing-mode: vertical-rl;
li { margin-left: 0; margin-top: 50px; width: auto; height: 200px; }
li:first-child { margin-top: 0; }}- I am text message no. 1 and I come first in the list
- I am text message no. 2 and I come second in the list
- I am text message no. 3 and I come third in the list
We’ve achieved the desired layout in all cases, but our CSS has become increasingly complex, requiring many additional rules. Imagine doing this for every element in a large project! This is where CSS logical properties come into play.
Introducing CSS Logical Properties
Traditional CSS properties define layout using physical dimensions. For instance, width denotes horizontal size, height denotes vertical size and margin-left specifies the left margin. In contrast, CSS logical properties define layout based on the logical flow of the content. For instance, inline-size denotes the size of the element in the dimension which is parallel to the flow of text, block-size denotes the size in the dimension perpendicular to the flow of text, etc.
Here are some common logical properties:
inline-sizeinstead ofwidthblock-sizeinstead ofheightmargin-inline-startinstead ofmargin-leftmargin-inline-endinstead ofmargin-rightmargin-block-startinstead ofmargin-topmargin-block-endinstead ofmargin-bottompadding-inline-startinstead ofpadding-leftpadding-inline-endinstead ofpadding-rightpadding-block-startinstead ofpadding-toppadding-block-endinstead ofpadding-bottominset-inline-startinstead ofleftinset-inline-endinstead ofrightinset-block-startinstead oftopinset-block-endinstead ofbottom- …and many more
You can find the full list of logical properties on MDN.
Here’s how we can refactor our widget to use logical properties:
.horizontal-list { list-style: none; white-space: nowrap; padding: 0; margin: 0;
li { white-space: normal; margin-inline-start: 50px; inline-size: 200px; display: inline-block; vertical-align: top; }
li:first-child { margin-inline-start: 0; }}This setup works seamlessly in different text directions:
LTR (Left-to-Right):
- I am text message no. 1 and I come first in the list
- I am text message no. 2 and I come second in the list
- I am text message no. 3 and I come third in the list
RTL (Right-to-Left):
- I am text message no. 1 and I come first in the list
- I am text message no. 2 and I come second in the list
- I am text message no. 3 and I come third in the list
Vertical RTL:
- I am text message no. 1 and I come first in the list
- I am text message no. 2 and I come second in the list
- I am text message no. 3 and I come third in the list
Browser Support
CSS logical properties boast good cross-browser support, so you can confidently implement them in your projects. For detailed compatibility, check caniuse.
Flexbox and Grid with Logical Properties
Both Flexbox and Grid layouts inherently support logical dimensions. Here’s how we can rewrite our widget using Flexbox:
.horizontal-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: row; justify-content: flex-start; gap: 50px;
li { inline-size: 200px; flex-shrink: 0; }}The output remains consistent across text directions, making it easier to maintain a responsive design.
In conclusion, leveraging CSS logical properties simplifies the process of creating layouts that adapt to different languages and writing modes, enhancing both your code’s maintainability and your website’s global accessibility.