Physical vs logical CSS properties

Learn how physical and logical CSS properties differ, how they map in RTL, and when a fixed physical side is still the correct choice.

Guide14 min read

margin-left and margin-inline-start can produce the same English screenshot. That does not make them interchangeable.

The first says, “put space on the physical left.” The second says, “put space before this box in the inline flow.” In English those instructions happen to agree. In Arabic they do not: inline start is on the right, while physical left remains left. The screenshot was identical because the assumptions had not yet been asked a difficult question.

Logical CSS is right when a relationship follows content flow. Physical CSS is right when a relationship follows the screen, a diagram, an image or another fixed coordinate system. Neither family is a compatibility mode for the other. The work is deciding which coordinate system the design means.

Two coordinate systems describe the same box#

Physical CSS names visible sides and dimensions:

  • top, right, bottom and left;
  • width and height;
  • top-left, top-right, bottom-right and bottom-left corners;
  • horizontal and vertical offsets.

These names do not change with document direction. padding-left remains left in English, Arabic and a nested LTR widget inside an Arabic page.

Logical CSS names sides and dimensions relative to writing flow:

  • block start and block end;
  • inline start and inline end;
  • block size and inline size;
  • corners formed where logical sides meet.

The CSS Logical Properties and Values specification defines flow-relative counterparts for many physical box-model properties. Their mapping depends on writing-mode, direction and text-orientation. MDN's logical properties overview explains the same model in terms of block and inline axes.

For the horizontal writing mode used by most English and Arabic interfaces, the block axis runs from top to bottom. The inline axis runs through each line of text. English inline flow starts on the left; Arabic inline flow starts on the right.

That gives the familiar mapping:

Logical sideHorizontal LTRHorizontal RTL
Block startTopTop
Block endBottomBottom
Inline startLeftRight
Inline endRightLeft

Direction reverses inline start and end. It does not reverse block start and end in horizontal-tb. A vertical writing mode changes the physical orientation of both axes, which is why “logical means RTL-aware left and right” is an incomplete definition. Logical means writing-flow-aware. RTL is one useful consequence.

Start and end need an axis#

The words start and end are meaningful only after you know the axis.

Inline start is where a line begins. Inline end is where it finishes. In horizontal Arabic, inline start is right and inline end is left.

Block start is where the sequence of blocks begins. Block end is where it continues toward. In a normal horizontal page, paragraphs stack from top to bottom, so block start is top and block end is bottom.

This declaration therefore describes a text-flow relationship:

css
.note {
  margin-inline-start: 1rem;
  padding-block: 0.75rem;
}

The margin moves from left in LTR to right in RTL. The block padding stays on top and bottom. One rule expresses both results without knowing which physical side inline start will occupy.

Writing modes are the reason the vocabulary has two axes instead of a more cheerful pair called “Arabic left” and “Arabic right.” In vertical-rl, lines of text run vertically, so inline size corresponds to physical height, while blocks progress horizontally. MDN's basic guide to logical properties illustrates how the axes rotate.

Even if your product supports only horizontal English and Arabic, the axis model is useful. It makes the intent explicit and stops developers from memorising replacements without understanding why they work. Memorised tables are fine until a nested writing mode or a slightly unusual component arrives carrying paperwork.

Physical and logical property mapping#

The following table assumes writing-mode: horizontal-tb. The right column is a logical counterpart only when the design relationship follows that axis.

Physical property or valueFlow-relative counterpart
widthinline-size
heightblock-size
min-widthmin-inline-size
max-widthmax-inline-size
min-heightmin-block-size
max-heightmax-block-size
margin-leftmargin-inline-start in LTR
margin-rightmargin-inline-end in LTR
margin-topmargin-block-start
margin-bottommargin-block-end
padding-leftpadding-inline-start in LTR
padding-rightpadding-inline-end in LTR
padding-toppadding-block-start
padding-bottompadding-block-end
border-leftborder-inline-start in LTR
border-rightborder-inline-end in LTR
leftinset-inline-start in LTR
rightinset-inline-end in LTR
topinset-block-start
bottominset-block-end
text-align: lefttext-align: start in LTR
text-align: righttext-align: end in LTR
float: leftfloat: inline-start in LTR
float: rightfloat: inline-end in LTR

The repeated “in LTR” matters. It says which logical relationship reproduces the existing English result. It does not say that physical left is another name for inline start. On an RTL element, left corresponds to inline end.

The MDN margin, border and padding guide lists the box-model mappings and the logical shorthands. Its positioning guide covers logical insets, floats and alignment values.

Do not convert from the property name alone. right: 1rem becomes inset-inline-end: 1rem only when the element belongs at reading end. If it belongs one rem from the physical right edge of a coordinate canvas, right is already saying the correct thing.

Use logical CSS for content relationships#

Consider a building-plan editor. Beside the drawing, a reviewer can leave an Arabic safety note. The note uses a start-side border and indentation to show that it belongs to a review thread.

Problem

html
<article class="plan-comment">
  <p class="plan-comment__team">فريق السلامة</p>
  <p>يجب إبقاء الممر المؤدي إلى السلم خالياً.</p>
  <button type="button">حل الملاحظة</button>
</article>
css
.plan-comment {
  margin-left: 2rem;
  padding-left: 1rem;
  border-left: 0.25rem solid #b42318;
  text-align: left;
}

In English, the comment is indented from reading start, its accent sits on reading start and its text aligns there. On an RTL page, the Arabic reader expects those relationships on the right. The physical declarations remain left, so the component keeps its English geometry while its content begins at the other edge.

The browser is following the declarations accurately. They describe a left-side design.

Better

css
.plan-comment {
  margin-inline-start: 2rem;
  padding-inline-start: 1rem;
  border-inline-start: 0.25rem solid #b42318;
  text-align: start;
}

In LTR, the result is unchanged. In RTL, each relationship maps to the right. The margin, padding, border and alignment move together because they all describe inline start.

Ritla check R030 names direction-sensitive physical properties without an RTL override. R022 names text-align: left explicitly set on majority-Arabic text. A report can identify those physical assumptions; it cannot decide whether the component meant “left” or “start.” That distinction comes from the design's job.

Flow-relative CSS is a good fit for:

  • spacing before or after labels, controls and list items;
  • leading accents and trailing dividers;
  • actions at the beginning or end of a reading sequence;
  • text alignment tied to language direction;
  • the first and last corners of inline groups;
  • text measures and component sizes tied to the writing axis.

The shared test is simple: if the component changes from LTR to RTL, should this relationship move to the corresponding side of the content? If yes, logical CSS probably names it better.

Keep physical CSS for spatial truth#

The same building-plan editor also contains a drawing with coordinates supplied by the plan. A marker attached to the west wall must stay there when the surrounding interface becomes Arabic.

css
.floor-plan {
  position: relative;
}

.floor-plan__west-exit {
  position: absolute;
  left: 6%;
  top: 48%;
}

Replacing left with inset-inline-start would move the marker to the right under RTL. The interface would be mirrored; the building would not. This is an impressive way to mislabel an exit.

Physical CSS is appropriate when a value belongs to:

  • a map, floor plan or technical diagram;
  • a chart axis or fixed plotting coordinate;
  • a viewport edge that must stay physically fixed;
  • a crop, hotspot or annotation tied to an image;
  • a print edge or physical page feature;
  • a fixed light source or depth treatment;
  • centering on a physical horizontal or vertical axis;
  • artwork whose geometry does not change with language.

Physical properties are not old syntax awaiting moral improvement. They describe physical constraints. The mistake is using them as accidental stand-ins for reading start and end.

Document intentional physical uses. A comment beside left: 6% can state that the value comes from floor-plan coordinates and must not mirror. Without that note, a later RTL audit may “fix” it into the wrong room.

Width is not always inline size#

In horizontal writing, width and inline-size produce the same dimension. They express different intent.

inline-size controls the size along the inline axis. It maps to width in horizontal writing and height in vertical writing. block-size controls the other axis. Their min and max forms follow the same model.

Use logical sizing when the constraint belongs to text or flow:

css
.plan-comment {
  max-inline-size: 38rem;
}

This limits the measure of the comment along the line-writing axis. In horizontal English and Arabic, that means maximum width. In a vertical writing mode, it means maximum height.

Keep physical sizing when the dimension is inherently physical:

css
.floor-plan__viewport {
  width: 48rem;
  height: 30rem;
}

A fixed canvas, video frame, exported preview or bitmap crop may need those physical dimensions regardless of writing mode. Replacing every width with inline-size does not make a stylesheet more international. It changes the contract of the dimension.

RTL alone does not swap width and height, so logical sizing is not required merely to support Arabic. Its value appears when a component is designed around writing axes or may support vertical modes. Use it where the axis is part of the meaning, not as a decorative synonym.

Logical corners use two axis names#

Physical radius properties name one fixed corner: border-top-left-radius, for example. Logical radius properties name the two sides that meet at the corner.

The first direction word is the block side. The second is the inline side:

Logical radiusHorizontal LTRHorizontal RTL
border-start-start-radiusTop-leftTop-right
border-start-end-radiusTop-rightTop-left
border-end-start-radiusBottom-leftBottom-right
border-end-end-radiusBottom-rightBottom-left

To round both corners on reading start:

css
.plan-comment {
  border-start-start-radius: 0.75rem;
  border-end-start-radius: 0.75rem;
}

An equal radius on all four corners is symmetric and needs no logical rewrite:

css
.dialog {
  border-radius: 0.75rem;
}

The physical shorthand becomes direction-sensitive when its corners differ. border-radius: 1rem 0 0 1rem remains tied to top-left, top-right, bottom-right and bottom-left in that order. It does not reverse in RTL. Use logical corner longhands when the asymmetric shape marks flow start or end; keep physical corner values when the shape belongs to fixed artwork or a physical attachment.

There is no need to turn four equal corners into four longer declarations. The browser does not award points for visible effort.

Logical shorthands are not physical shorthands reordered#

Physical four-side shorthands use top, right, bottom, left order. Logical shorthands address one axis at a time.

css
.panel {
  margin-block: 1rem 2rem;
  margin-inline: 0.75rem 1.5rem;
}

For margin-block, the first value is block start and the second is block end. For margin-inline, the first is inline start and the second is inline end. Under RTL, the inline values map to opposite physical sides; their written order does not reverse.

One-value logical shorthands apply to both sides of their axis:

css
.panel {
  padding-block: 1rem;
  padding-inline: 1.5rem;
  border-inline: 1px solid #d0d5dd;
}

border-inline sets both inline borders. It is not a shorter form of border-inline-start. The names differ by one word and by an entire side of the component, which is a generous amount of consequence for six characters.

The ordinary margin, padding, border and inset shorthands remain useful for symmetric or intentionally physical values. padding: 1rem is direction-neutral because every side receives the same value. padding: 1rem 2rem is also symmetric across each axis. A four-value shorthand with unequal left and right values is physical and needs an intent check.

Expanding an asymmetric shorthand during review can make that intent visible:

css
.toolbar {
  padding-block-start: 0.75rem;
  padding-inline-end: 2rem;
  padding-block-end: 1rem;
  padding-inline-start: 1.25rem;
}

The longer form is justified when the four values mean four different relationships. If they are all the same, brevity may remain peacefully employed.

Flex and grid add layout-relative start#

Physical and flow-relative coordinates are not the only directional language in CSS. Flexbox and grid also use alignment relative to their layout axes.

In a normal flex row, the main axis follows the inline axis. In an RTL container, the row starts on the right. justify-content: flex-start aligns items at the main-start edge, while align-items: flex-start uses cross start. If flex-direction changes to column, main start is now on the block axis.

This distinction matters:

  • text-align: start refers to inline start;
  • margin-inline-start refers to inline start;
  • justify-content: flex-start refers to the flex container's main start;
  • align-items: start resolves on the alignment axis used by that layout context;
  • left always refers to physical left.

Do not replace a flex alignment value with a margin just because both happen to put something on the left in one screenshot. They control different relationships.

A normal row already responds to direction:

css
.plan-tools {
  display: flex;
  gap: 0.5rem;
}

Adding row-reverse to “support RTL” reverses the row a second time. The first item moves left, while focus order still follows the DOM. R081 names a flex row-reverse used to fake RTL when tab order fights visual order. Let direction establish inline flow; use reverse values only when the content sequence itself is intentionally reversed.

Grid auto-placement also starts from the direction-aware start edge. Explicit tracks, areas and line placement can encode further assumptions, so test the grid rather than presuming every authored placement mirrors. The RTL CSS guide covers flex and grid behavior in more depth.

Some effects have no logical counterpart#

Not every directional-looking feature has a logical form. The following remain physical unless you supply different values:

  • translateX() and transform matrices;
  • horizontal box-shadow offsets;
  • background-position: left or right;
  • gradient angles and stop positions;
  • clip-path and motion-path coordinates;
  • SVG path geometry and viewBox coordinates;
  • image content itself.

For those effects, first decide whether the meaning should mirror. Then provide an RTL value if it should.

A small directional nudge can use a custom property:

css
.plan-link {
  --inline-shift: 0.25rem;
}

.plan-link:dir(rtl) {
  --inline-shift: -0.25rem;
}

.plan-link:hover .plan-link__icon {
  transform: translateX(var(--inline-shift));
}

translateX() uses the physical x-axis, so its sign does not follow dir. A transform that represents movement toward reading end should change sign. A transform that pans a fixed plan coordinate may need to stay unchanged. R033 applies when translateX moves an element off-screen in RTL; smaller directional errors still require visual testing.

Shadows need the same judgment. A fixed light source should generally keep its physical horizontal offset. A shadow used as a directional edge treatment may need an RTL counterpart. R032 names a direction-sensitive shadow x-offset without one.

Do not mirror an entire component to fix an icon or one background shape. Text, media, coordinates and focus indicators will mirror too. Apply the exception to the smallest element whose meaning requires it. CSS will happily flip the whole room because one sign points the wrong way. It was not invited to the planning meeting.

The element's direction chooses the mapping#

Logical properties map from the direction and writing mode of the element they style. They do not read a single permanent direction from the page and stop thinking.

Suppose the Arabic plan editor contains an English inspector note:

html
<aside class="review-panel">
  <p class="review-panel__label">مراجعة خارجية</p>
  <blockquote class="review-panel__quote" lang="en" dir="ltr">
    Keep the access route clear near the western stair.
  </blockquote>
</aside>

If the panel accent belongs to the Arabic interface, style the outer panel:

css
.review-panel {
  border-inline-start: 0.25rem solid #175cd3;
  padding-inline-start: 1rem;
}

The panel inherits RTL, so its logical start is right. The inner quotation uses LTR for its English content. Placing the logical border on the quotation instead would make its start edge left. That can also be right, but it expresses a different relationship: the accent would belong to the English quote rather than the Arabic panel.

Put a flow-relative declaration on the box whose flow gives it meaning. Use wrappers when placement direction and content direction differ. The HTML direction guide explains how to establish those boundaries in markup.

This is also why a root-only [dir="rtl"] override can mishandle nested LTR components. The ancestor matches even when the styled descendant has its own LTR direction. The :dir(rtl) pseudo-class is better for a rule that should follow the element's actual directionality, provided direction comes from HTML rather than only from CSS.

Physical and logical declarations share the cascade#

A physical property and its mapped logical counterpart are not two independent layers. Once the browser knows the element's writing mode, paired properties share a computed value. The declaration with higher cascade priority wins.

css
.plan-comment {
  margin-inline-start: 2rem;
  margin-left: 0;
}

In LTR, inline start maps to left, so both declarations target the same margin. The later margin-left wins and removes it. In RTL, inline start maps to right, so the left reset affects the opposite side and the right margin remains.

The same source order produces a different collision because the mapping changes. The specification calls these related sets logical property groups and defines how physical and flow-relative declarations cascade together.

Avoid mixing vocabularies for the same relationship. During migration, remove obsolete physical declarations and inspect broad shorthands such as margin, padding, border and inset that may reset a mapped side later. Cascade layers, specificity, source order and !important still operate. Logical properties have good semantics, not diplomatic immunity.

In DevTools, inspect:

  1. the element's computed direction and writing-mode;
  2. the logical declaration and the physical side it maps to;
  3. crossed-out physical or logical declarations;
  4. later shorthands and state selectors;
  5. nested direction boundaries.

If a logical rule works in one direction but not the other, a physical collision is a strong suspect. It is not the only suspect, but it is unusually fond of leaving this exact calling card.

Put the distinction into tokens and APIs#

Styles stay readable when tokens and component props preserve the coordinate system.

Flow-relative tokens might be named:

css
:root {
  --space-inline-start: 1rem;
  --panel-inline-size: 24rem;
  --accent-start-width: 0.25rem;
}

Physical tokens might be named:

css
:root {
  --map-west-gutter: 1rem;
  --canvas-height: 30rem;
  --shadow-x: 0.25rem;
}

Do not rename a physical token to sound logical while leaving its consumers physical. A token name is documentation, not an enchantment.

Component APIs need the same honesty. placement="start" should follow the component's direction. placement="left" should stay left. If both uses exist, support both concepts or expose a narrower API that names the product choice, such as placement="reading-edge" for a note and coordinate props for a floor-plan marker.

A design handoff that says “16 pixels on the left” should trigger one follow-up question: does this mean left, or does it mean before the content in the current mockup? The answer determines the CSS. No amount of later refactoring can recover intent that was never recorded.

Test the meaning, not only the mirror#

Render the same component with dir="ltr" and dir="rtl". Keep markup and data constant so direction is the variable. Then verify both logical movement and intentional physical stability.

Test caseLTRRTL
Start-side comment accentLeftRight
End-side actionRightLeft
Block-start dividerTopTop
Equal corner radiusUnchangedUnchanged
Start-side asymmetric cornersLeft cornersRight corners
West-wall plan markerLeft coordinateSame left coordinate
Normal flex rowStarts leftStarts right
Physical canvas sizeSame width and heightSame width and height

Test nested direction too. Place an LTR content block inside the RTL page and decide whether each logical edge belongs to the outer UI or the inner content. If changing the inner dir moves an accent that should belong to the surrounding panel, the declaration is attached to the wrong box.

Check every state that changes directional CSS: selected borders, validation marks, open menus, sticky controls, hover motion and focus treatment. Resize the viewport and use long Arabic labels. Logical placement can be correct while fixed widths or absolute children still cause overlap and overflow.

For each physical declaration found in an audit, write one of three decisions:

  • convert, because the relationship follows content flow;
  • keep, because the relationship is physically fixed;
  • override, because the effect should mirror but has no logical form.

That classification is more useful than a rule banning left and right. A ban hides valid coordinates. A decision records why they exist.

Choose the coordinate system on purpose#

Physical CSS answers where something sits in physical space. Logical CSS answers where it sits in writing flow. Flex and grid alignment can answer where it sits on a layout axis. The correct declaration is the one that names the relationship the component actually has.

A free Ritla scan can surface direction-sensitive physical properties without an RTL override R030, physical floats without an override R031 and directional shadow offsets without an RTL counterpart R032. Review each finding as a coordinate-system decision, then use what should be mirrored in RTL when the unresolved question belongs to the design rather than the stylesheet.

Use logical properties for flow, physical properties for space, and explicit exceptions for effects that live in both worlds. The difficult part is choosing. The syntax, for once, is mostly behaving itself.

Checks in this guide

See what your Arabic pages are hiding

Paste a URL. Ritla renders the page on desktop and mobile, runs every check, and shows the top issues with screenshot evidence.