Hoppa till huvudinnehåll

Physical properties to logical properties

· 9 min att läsa
Filip Tammergård
Software Engineer at Einride

In the last months, I have been diving into the beautiful world of logical properties. The CSS spec has one sentence that I think describes what logical properties are in a nice way:

[Logical] properties are writing-mode relative equivalents of their corresponding physical properties.

Physical properties are simple to reason about, since they represent physical directions. Top, right, bottom and left are absolute directions. Left is always left—simple as that. Logical properties, on the other hand, are relative—the physical direction they correspond to varies.

As mentioned, the absolute nature of physical properties makes them simple to reason about. However, the absolute nature is also a limitation.

The problem with physical properties

Let's say we want to display a qoute with a red border to the left together with some padding:

<blockquote>Hello</blockquote>
blockquote {
border-left: 2px solid red;
padding-left: 1rem;
}

Result:

Hello

Cool!

But what happens if we translate the paragraph to Arabic? Arabic has a right-to-left text direction, so let's specify that with dir="rtl", and also provide mark that Arabic is used in the paragraph with lang="ar".

But what happens if this is done in a language with a right-to-left text direction? Let's try updating the text direction while keeping the same CSS:

<blockquote dir="rtl" lang="ar">أهلا</blockquote>

Result:

أهلا

That's not what we want... 😕

When the text direction is changed, we want the margin to be updated with it. But left is still left, even when the text direction is changed.

Enter logical properties

Let's try using logical properties instead!

<blockquote>Hello</blockquote>
blockquote {
border-inline-start: 1px solid red;
padding-inline-start: 2rem;
}

Result:

Hello

Let's see what happens now when translating to Arabic.

Let's try to change the text direction again while keeping the same CSS.

<blockquote dir="rtl" lang="ar">أهلا</blockquote>

Result:

أهلا

Yeah! 🎉

I scratched my head a lot when I started converting physical properties to their logical equivalents. During the process, I made some conversion tables for future reference.

Converting to logical properties

In the following conversion tables, the baseline text direction is left-to-right, top-to-bottom, as regular English.

Padding

Here's how physical padding properties are converted to logical:

Physical propertyLogical property
padding-toppadding-block-start
padding-rightpadding-inline-end
padding-bottompadding-block-end
padding-rightpadding-inline-start

Shorthands

The padding property is a shorthand that enables setting padding in multiple directions in one declaration. padding: 1rem; sets 1rem padding in all four directions. Since it sets the same padding in all direction, there's no need to convert to logical—it would still have the same result.

But consider this padding declaration:

p {
padding: 1rem 2rem;
}

That's a shorthand for these declarations:

p {
padding-top: 1rem;
padding-bottom: 1rem;
padding-left: 2rem;
padding-right: 2rem;
}

In logical property land, this is the equivalent:

p {
padding-block: 1rem;
padding-inline: 2rem;
}
anteckning

In physical property land, setting top and bottom padding is commonly done with the shorthand padding: 1rem 0;. However, this sets left and right padding to the default value 0 as a "side effect". The logical padding-block: 1rem; is not truly equivalent, as left and right padding is not set in that case.

Setting default values when there's no need for unsetting, just to be able to use the shorthands, might be considered bad practice. This is another reason why padding-block and padding-inline are great replacements for the padding shorthand in many cases!

Margin

Logical margin properties work in the exact same way as logical padding properties. Here's the conversion table:

Physical propertyLogical property
margin-topmargin-block-start
margin-rightmargin-inline-end
margin-bottommargin-block-end
margin-rightmargin-inline-start

The margin property has also has shorthands equivalent to the padding shorthands.

Proposal for flow-relative margin shorthand

In the future, we might have a margin-logical, as a logical shorthand equivalent to the physical margin shorthand. See the proposal discussion here: https://github.com/w3c/csswg-drafts/issues/1282

Borders

Here's the conversion table for border properties:

Physical propertyLogical property
border-topborder-block-start
border-rightborder-inline-end
border-bottomborder-block-end
border-leftborder-inline-start

border-top-{color|style|width} can also be converted to border-block-start-{color|style|width}, exactly as you would imagine. I won't add these to the conversion table to avoid making it too cluttered.

Shorthands

A logical property shorthand addition is that you can set block and inline borders, respectively, in one declaration:

Physical declarationLogical declaration
border-top: 1px solid red;
border-bottom: 1px solid red;
border-block: 1px solid red;
border-left: 1px solid red;
border-right: 1px solid red;
border-inline: 1px solid red;

Border radii

Converting border radius to logical requires thinking about the order of properties carefully. The format is border-{block-direction}-{inline-direction}-radius:

Physical propertyLogical property
border-top-left-radiusborder-start-start-radius
border-top-right-radiusborder-start-end-radius
border-bottom-right-radiusborder-end-end-radius
border-bottom-left-radiusborder-end-start-radius

Sizing

Here's the conversion table for sizing properties:

Physical propertyLogical property
heightblock-size
min-heightmin-block-size
max-heightmax-block-size
widthinline-size
min-widthmin-inline-size
max-widthmax-inline-size

Alignment

As you might have noticed, physical directions like left and right don't exist at all in logical property land. That's not only true for property names, but also for values. left can mostly be converted to start and right to end.

Physical declarationLogical declaration
text-align: left;text-align: start;
text-align: right;text-align: end;
justify-content: left;justify-content: start;
justify-content: right;justify-content: end;
anteckning

The justify-content property accepts start and end as values, but also flex-start and flex-end. So what's the difference? The main difference is browser support. flex-{start|end} has better support, but start|end will replace the flex values eventually.

Positioning

For positioning, we're going to start working a lot with inset in different shape and forms.

Physical propertyLogical property
topinset-block-start
rightinset-inline-end
bottominset-block-end
leftinset-inline-start

Shorthands

There are some useful shorthands as well!

Physical declarationLogical declaration
top: 0;
bottom: 0;
inset-block: 0;
left: 0;
right: 0;
inset-inline: 0;
top: 0;
right: 0;
bottom: 0;
left: 0;
inset: 0;
anteckning

There's also an inset shorthand, that sets offsets in all directions. However, it defines physical offsets rather than logical.

Scroll margin and scroll padding

Here's the conversion table for scroll margin and scroll padding:

Physical propertyLogical property
scroll-padding-topscroll-padding-block-start
scroll-padding-rightscroll-padding-inline-end
scroll-padding-bottomscroll-padding-block-bottom
scroll-padding-leftscroll-padding-inline-start
scroll-margin-topscroll-margin-block-start
scroll-margin-rightscroll-margin-inline-end
scroll-margin-bottomscroll-margin-block-bottom
scroll-margin-leftscroll-margin-inline-start

Shorthands

Here are some shorthands:

Physical declarationLogical declaration
scroll-margin-top: 1px;
scroll-margin-bottom: 1px;
scroll-margin-block: 1px;
scroll-margin-left: 1px;
scroll-margin-right: 1px;
scroll-margin-inline: 1px;
scroll-padding-top: 1px;
scroll-padding-bottom: 1px;
scroll-padding-block: 1px;
scroll-padding-left: 1px;
scroll-padding-right: 1px;
scroll-padding-inline: 1px;

Browser support

Logical properties are not supported in Internet Explorer. But since it has reached end-of-life, we might not need to consider that. Other than that, browser support is generally great.

There are a few exceptions, though.

Logical vs physical properties

It might be tempting to do a complete migration from physical to logicl properties, and perhaps even add some kind of linting rule that prevents physical properties from being used. However, physical properties are not deprecated in any sense. In some situations, it does not make sense to convert. Here's an example from the CSS specification:

Documents might need both logical and physical properties. For instance the drop shadows on buttons on a page must remain consistent throughout, so their offset will be chosen based on visual considerations and physical directions, and not vary by writing system.

It's important to remember that left is always left. If you say that something is placed on the left side of the screen, left should be used rather than inset-inline-start.

Stay pragmatic!

Logical units

We have been talking a lot about logical properties here, and a little bit about logical values. But what about units? Let me explain with an example declaration:

inline-size: 70vw;

Does it ring a bell? It probably should. In this declaration, the logical inline-size property is used, but the declaration value 70vw is physical. In other words, inline-size can define the horizontal or vertical size depending on writing mode, while 70vw is always calculated based on the horizontal size undependent on the writing mode. In practice, we probably want the value to be flow relative as well in this case.

The units vb and vi can make this happen! vb is the percentage the viewport's block size, while vi is the percentage of the viewport's inline size. So here's what you can do instead to make the value flow relative:

inline-size: 70vi;

Here it is in table format:

Physical unitLogical unit
vh vb
vw vi

Conclusion

  • Logical properties are awesome!
  • Both logical and physical properties might be needed. Think about whether something should be relative to writing mode or not when you choose between logical and physical properties.
  • Consider browser support before using logical properties.

References