Skip to content
ZA

Blog3 min read

How I Reduced RTL CSS Code Using Logical Properties

I share how I simplified Arabic RTL support at Travelwings by replacing duplicated left/right CSS overrides with logical properties such as margin-inline-start, making one layout work naturally in both LTR and RTL.

Side-by-side travel search interface layouts showing UI elements and spacing automatically mirroring from left-to-right to right-to-left using CSS logical properties.

While working on Arabic RTL support at Travelwings, I faced a common frontend issue: a lot of our existing UI had been built with left, right, margin-left, and padding-right values.

Previously, RTL support was handled with separate CSS rules targeting the page direction, something like this:

css
[dir='rtl'] .flight-card {
  margin-right: 16px;
  margin-left: 0;
  text-align: right;
}

[dir='ltr'] .flight-card {
  margin-left: 16px;
  margin-right: 0;
  text-align: left;
}

This worked, but it meant I had to write and maintain extra RTL overrides for many components. As the product grew, those overrides became difficult to manage. A small UI change could require checking both the default CSS and the RTL-specific CSS.

Then I started using CSS logical properties.

Instead of writing CSS based on physical directions like left and right, logical properties work according to the document direction. So the same CSS automatically adapts for English (LTR) and Arabic (RTL).

For example, instead of this:

css
.card {
  margin-left: 16px;
}

I used:

css
.card {
  margin-inline-start: 16px;
}

In an English LTR layout, margin-inline-start means margin-left.

In an Arabic RTL layout, it automatically becomes margin-right.

That means one line of CSS supports both directions without an extra [dir='rtl'] override.

Here are some of the logical properties I started using regularly:

Traditional CSS

Logical CSS

margin-left

margin-inline-start

margin-right

margin-inline-end

padding-left

padding-inline-start

padding-right

padding-inline-end

border-left

border-inline-start

border-right

border-inline-end

left

inset-inline-start

right

inset-inline-end

top

inset-block-start

bottom

inset-block-end

width

inline-size

height

block-size

For example, a search input icon that previously needed separate rules can become much cleaner:

css
.search-input__icon {
  position: absolute;
  inset-inline-start: 12px;
}

.search-input {
  padding-inline-start: 40px;
}

Now the icon appears on the left in English and on the right in Arabic automatically. The input padding also follows it correctly.

Another useful example is borders:

css
.item {
  border-inline-start: 3px solid #ff7a00;
  padding-inline-start: 12px;
}

In LTR, the orange border appears on the left. In RTL, it moves to the right without writing any Arabic-specific CSS.

This approach helped me remove a large amount of duplicated RTL CSS from the project. It also made components easier to reuse, because their layout was no longer tied to one writing direction.

I still needed direction-specific styling in a few cases, especially where an icon itself needed to be flipped or where a layout had a very specific visual requirement. But for spacing, positioning, borders, and many alignment cases, logical CSS properties made RTL support much more maintainable.

For any product that supports both English and Arabic, I would strongly recommend considering logical properties from the start. It saves time, reduces CSS duplication, and makes the codebase much easier to maintain as the product grows.

Useful MDN references: