Now that cross-browser support is at a tipping point, it’s a good time to take a look at logical properties and values. If you’re creating a website in multiple languages, logical properties and values are incredibly useful. Even if you’re not, there are still some convenient new shorthands it’s worth knowing about.
For example, I’ve lost count of the amount of times I’ve written this to center something:
.thing {
margin-left: auto;
margin-right: auto;
}
We could make it a one-liner with something like margin: 0 auto;
but then the top and bottom margins get thrown into the mix. Instead, we can select just the left and right margin with the margin-inline
logical property.
Start thinking of things as “inline” or “block”
That last demo is pretty neat, right? The margin-inline
property sets both margin-left
and margin-right
. Similarly, the margin-block
property sets both margin-top
and margin-bottom
. And we’re not only talking margins. Logical properties has similar shorthands to set border
and padding
. So if you have a visual design that calls for borders only on the sides, you can just use border-inline
instead of fussing with each physical direction on its own.
So, as we move ahead, we now know that we’re dealing with inline and block directions instead of physical directions. Inline handles the left and right directions, while block manages top and bottom.
That is, until things get swapped around when the writing-mode changes.
Pay attention to direction and writing mode
What we’ve seen so far are examples of CSS logical properties. These are versions of CSS properties were used to like margin
and padding
, but written in a new way that forgoes physical directions (i.e. left, right, top, and bottom).
CSS was developed with the English language in mind and English is written and read from left-to-right. That’s not the case for all languages though. Arabic, for example, is read from right-to-left. That’s why HTML has a dir
attribute.
<html dir="rtl">
CSS has an equivalent property (although it’s recommended to use the HTML attribute just in case the CSS fails to load):
.foreign-language { direction: rtl; }
Chinese, Japanese, Korean and Mongolian can be written either horizontally from left-to-right, or vertically from top to bottom. The majority of websites in these languages are written horizontally, the same as with English.
Comparatively, vertical writing is more common on Japanese websites. Some sites use a mixture of both vertical and horizontal text.
When written vertically, Chinese, Japanese and Korean are written with the top-right as a starting point, whereas Mongolian reads from left to right. This is exactly why we have the writing-mode
property in CSS, which includes the following values:
horizontal-tb
: This is the default value, setting the the direction left-to-right for languages like English or French, and right-to-left languages like Arabic. Thetb
stands for “top-to-bottom.”vertical-rl
: This changes the direction to right-to-left in a vertical orientation for languages like Chinese, Japanese and Korean.vertical-lr
: This is used for vertical left-to-right languages, like Mongolian.
CSS logical properties offer a way to write CSS that is contextual. When using logical properties, spacing and layout are dependent on both the writing-mode
and direction (whether set by either CSS or HTML). It therefore becomes possible to reuse CSS styles across different languages. BBC News, for example, rebuild their website in over a dozen languages. That’s a better experience than leaving users to rely on autotranslate. It also means they can better cater specific content to different parts of the world. The visual styling though, remains much the same across regions.
Let’s look at the example below to see the shortcomings of physical properties. Using the physical margin-left property (shown in red), everything looks good in English. If you were to reuse the CSS but change the writing mode to rtl (shown at the bottom) there’s no space between the text and the icon and there’s excess white space on the left of the text. We can avoid this by using a logical property instead.
What makes logical properties and values so useful is that they will automatically cater to the context of the language. In a left-to-right language like English, margin-inline-start
will set the left-side margin. For a right-to-left language like Arabic, Urdu, or Hebrew, it will set the right-hand margin — which solves the layout problem in the above example. That’s right-to-left taken care of. If you have vertical text, margin-inline-start
will cater to that context to, adding the margin at the top, which is where you would start reading from in any vertical language (that’s why it’s called margin-inline-start
— just think about which direction you start reading from). The direction of inline
changes based on the element’s writing-mode
. When a vertical writing-mode
is set, it handles the vertical direction top and bottom. See how things can get switched around?
A complete list of logical properties and values
There are dozens of CSS properties that have a logical alternative syntax. Adrian Roselli has a handy visualization where you can toggle between the physical CSS properties that we’re all used to and their logical property equivalents. It’s a nice way to visualize logical properties and the physical properties they map to when the direction is ltr
and the writing-mode
is horizontal-tb
.
Let’s break all of those down even further and map each and every physical CSS property to its logical companion, side-by-side. The tables shown throughout this article show traditional physical CSS in the left column and their logical equivalents (using a left-to-right horizontal mapping) in the right column. Remember though, the whole point of logical properties is that they change based on context!
Sizing
In a horizontal writing mode, inline-size
sets the width of an element, while block-size
sets the height. In a vertical writing mode, the opposite is true: inline-size
sets the height and block-size
sets the width.
Physical property | Logical property |
---|---|
width | inline-size |
max-width | max-inline-size |
min-width | min-inline-size |
height | block-size |
max-height | max-block-size |
min-height | min-block-size |
Logical properties for sizing have good cross-browser support.
Borders
Everything here has solid cross-browser support among modern browsers.
Physical property | Logical property |
---|---|
border-top | border-block-start |
border-bottom | border-block-end |
border-left | border-inline-start |
border-right | border-inline-end |
Here’s an example of using border-inline-start
shown with English, Arabic, and Chinese.
Here’s an example that sets border-block-start
dotted and border-block-end
dashed:
There are also logical properties for setting the border color, width, and style individually:
Physical property | Logical property |
---|---|
border-top-color | border-block-start-color |
border-top-width | border-block-start-width |
border-top-style | border-block-start-style |
So, again, it’s about thinking in terms of “inline” and “block” instead of physical directions, like left
and top
. We also have shorthand logical properties for borders:
Physical property | Logical property |
---|---|
border-top and border-bottom | border-block |
border-left and border-right | border-inline |
Margin
Here are all the individual logical margin
properties:
Physical property | Logical property |
---|---|
margin-top | margin-block-start |
margin-bottom | margin-block-end |
margin-left | margin-inline-start |
margin-right | margin-inline-end |
These logical properties has comprehensive modern cross-browser support, including Samsung Internet, and has been supported in Safari since 12.2.
And, remember, we have the shorthands as well:
Physical property | Logical property |
---|---|
margin-top and margin-bottom | margin-block |
margin-left and margin-right | margin-inline |
Padding
Padding is super similar to margin. Replace margin
with padding
and we’ve got the same list of properties.
Physical property | Logical property |
---|---|
padding-top | padding-block-start |
padding-bottom | padding-block-end |
padding-left | padding-inline-start |
padding-right | padding-inline-end |
padding-top and padding-bottom | padding-block |
padding-left and padding-right | padding-inline |
Just like margins, logical properties for padding have good cross-browser support.
Positioning
Need to offset an element’s position in a certain direction? We can declare those logically, too.
Physical property | Logical property |
---|---|
top | inset-block-start |
bottom | inset-block-end |
left | inset-inline-start |
right | inset-inline-end |
top and bottom | inset-block |
left and right | inset-inline |
In a horizontal writing mode (either left-to-right, or right-to-left) inset-block-start
is equivalent to setting top
, and inset-block-end
is equivalent to setting bottom
. In a horizontal writing mode, with a left-to-right direction, inset-inline-start
is equivalent to left
, while inset-inline-end
is equivalent to right
, and vice-versa for right-to-left languages.
Conversely, for a vertical writing mode, inset-inline-start
is equivalent to top
while inset-inline-end
is equivalent to bottom
. If writing-mode
is set to vertical-rl
, inset-block-start
is equivalent to right
and inset-block-end
is equivalent to left
. If the writing-mode
is set to vertical-lr
, the opposite is the case and so inset-block-start
is equivalent to left
.
Logical property | Writing mode | Equivalent to: |
---|---|---|
inset-block-start | Horizontal LTR | top |
inset-block-start | Horizontal RTL | top |
inset-block-start | Vertical LTR | left |
inset-block-start | Vertical RTL | right |
Here’s an example of how the same CSS code for absolute positioning looks in each of the four different writing directions:
Logical properties for positioning are supported in all modern browsers, but only recently landed in Safari.
There’s also a new shorthand for setting all four offsets in one line of code. Here’s an example using inset
as a shorthand for setting top
, bottom
, left
, and right
in one fell swoop to create a full-page overlay:
I’ve heard inset
incorrectly referred to as a logical property. But, a quick look in DevTools shows that it is actually a shorthand for physical values, not logical properties:
What it’s actually doing is defining physical offsets (i.e. left, right, top and bottom) rather than logical ones (i.e. inline, block, start and end). Obviously if you want to set the same value for all four sides, as in the example above, it doesn’t matter.
inset: 10px 20px 5px 8px; /* shorthand for physical properties not logical properties */
Text alignment
Logical values for text alignment enjoy great browser support and have for many years. When working in English, text-align: start
is the same as text-align: left
, while text-align: end
is the same as text-align: right
. If you set the dir
attribute to rtl
, they switch and text-align: start
aligns text to the right.
Physical value | Writing mode | Equivalent to: |
---|---|---|
start | LTR | left |
start | RTL | right |
end | LTR | right |
end | RTL | left |
Border radius
So far everything we’ve looked at has decent browser support. However, there are some other logical properties where support is still a work in progress, and border radius is one of them. In other words, we can set a different border-radius
value for different corners of an element using logical properties, but browser support isn’t great.
Physical property | Logical property |
---|---|
border-top-left-radius | border-start-start-radius |
border-top-right-radius | border-start-end-radius |
border-bottom-left-radius | border-end-start-radius |
border-bottom-right-radius | border-end-end-radius |
It’s worth noting that the spec doesn’t include shorthand properties, like border-start-radius
and border-end-radius
. But, like I said, we’re still in early days here, so that might be a space to watch.
Floats
Flow-relative values for logical floats have terrible browser support at the time I’m writing this. Only Firefox supports inline-start
and inline-end
as float
values.
Physical value | Logical value |
---|---|
float: left | float: inline-start |
float: right | float: inline-end |
clear: left | clear: inline-start |
clear: right | clear: inline-end |
Other logical properties
There are proposed logical properties for overflow
and resize
, but they currently have horrendous browser support.
Physical | Logical |
---|---|
resize: vertical | resize: block |
resize: horizontal | resize: inline |
overflow-y | overflow-block |
overflow-x | overflow-inline |
Digging deeper
We explored what it means for a property to be considered “logical” and then mapped out all of the new logical properties and values to their physical counterparts. That’s great! But if you want to go even deeper into CSS Logical Properties and Values, there are a number of resources worth checking out.
- “RTL Styling 101” (Ahmad Shadeed): A great resource if you’re dealing with Arabic or other right-to-left languages. Ahmad covers everything, from logical properties to considerations when working with specific layout techniques, like flexbox and grid.
text-combine-upright
(CSS-Tricks): If you’re dealing with vertical text, did you know that this property can rotate text and squeeze multiple characters into the space of a single character? It’s a nice touch of refinement in specific situations where some characters need to go together but still flow with a vertical writing mode.
If you want to view some nice real-world examples of vertical typography from across the web, take a look at the Web Awards for Horizontal and Vertical Writings. There’s a lot of great stuff in there.
Wrapping up
Do you need to rush and swap all of the physical properties out of your codebase? Nope. But it also doesn’t hurt to start using logical properties and values in your work. As we’ve seen, browser support is pretty much there. And even if you’re working on a site that’s just in English, there’s no reason to not use them.
Well I think the logical properties are not short. Start, block-start, block-end, … I wonder if we put more weight for the css files. For me, directions left, right, top, bottom are more understandable than start and end to border, margin, padding.
Physical directions like left and right are relative to the writing mode and will cause issues when the writing mode is changed. It’s covered pretty extensively in the article.
If you have a valid reason for keeping physical directions over logical ones I’d love to read about it. (sincerely)
As much as I advocate for using logical properties, unfortunately using physical directions makes more sense sometimes, like when you are in LTR context within an RTL document.
For example, if you have an email address input box (which AFAIK should always be LTR) which you set a
dir="ltr"
on, and you also want to display an icon next to it,padding-inline-start
will be applied on the other side, because of the LTR directionality.So having something like
.parent:dir(rtl) .child { padding-right: 10px }
will make more sense in this case.@Ollie Williams
text-align-right should be text-align: right
The second table under https://css-tricks.com/css-logical-properties-and-values/#positioning has a stray apostrophe.
Thanks for the article!
@tommy Obviously. Effort and reward. You get the better result but you’ll have to work for it.
If you are using stylelint, this plugin can help:https://www.npmjs.com/package/stylelint-use-logical-spec
I have it set to warn me anytime an alternative logical property is available.
That way I learn as I encounter each new property rather than having to try and remember them all – which is a bit intimidating.
fwiw, Safari is about to get logical properties support for float and clear.
https://webkit.org/blog/11680/release-notes-for-safari-technology-preview-125/
Nice article! Thanks for sharing, and I’m going to translate it into Chinese so that more people can read it.