Logical Properties & Modern Color
Write direction-aware spacing that works in any language, and reach for perceptual colour functions like color-mix() and oklch() that power modern design systems.
What you will learn
- Use logical properties like margin-inline and padding-block
- Understand why they help internationalisation
- Mix and tweak colours with color-mix() and oklch()
The problem with top / right / bottom / left
Properties like margin-left and padding-right are physical — they always mean the same fixed side of the screen. That breaks for languages written right-to-left (like Arabic or Urdu), where “the start of the text” is on the right, not the left. You would have to rewrite every left/right value for those layouts.
Logical properties fix this by talking about start and end instead of left and right. They follow the reading direction automatically. The two key words are:
- inline — the direction text flows (left-to-right in English; right-to-left in Arabic).
- block — the direction lines stack (top to bottom).
| Physical (old) | Logical (new) | Means |
|---|---|---|
margin-left / margin-right | margin-inline | Space at the start and end of the text flow |
margin-top / margin-bottom | margin-block | Space above and below |
padding-left | padding-inline-start | Inner space at the text’s starting edge |
left / right / top / bottom | inset-inline / inset-block | Positioning offsets, direction-aware |
Logical properties in action
Below, the same card is shown in a left-to-right and a right-to-left context. Because it uses padding-inline and a logical border, the “start edge” accent automatically flips to the correct side — with no extra CSS:
<style>
.note {
padding-block: 10px; /* top + bottom */
padding-inline: 16px; /* start + end (L/R, direction-aware) */
border-inline-start: 4px solid #4338ca; /* accent on the START edge */
background: #eef2ff; border-radius: 8px; margin-block-end: 12px;
}
</style>
<div class="note">Left-to-right: the indigo accent is on the left (the start).</div>
<div class="note" dir="rtl">دائیں سے بائیں: لہجہ اب دائیں طرف ہے۔</div>Both boxes use the exact same CSS, yet the accent bar appears on opposite sides. That is the whole point:
padding-blocksets top + bottom;padding-inlinesets the two text-flow sides at once.border-inline-startdraws the accent on the start edge. In the English box, “start” is the left; in thedir="rtl"box, “start” becomes the right — so the accent flips automatically.- With old physical properties you would have needed a second rule (
border-right) just for the RTL version. Logical properties remove that duplication entirely.
Note: Output: The first note has its indigo accent bar on the left; the second note (set to right-to-left) shows the same accent on the right — without any extra CSS, because the border was defined on the logical “start” edge.
Modern colour: color-mix() and oklch()
You already know HEX, RGB and HSL. Modern CSS adds colour functions that design systems lean on. The two most useful:
color-mix(in oklch, A 70%, B)— blends two colours. Great for generating a hover shade from a base colour without hard-coding a second value.oklch(L C H)— a perceptual colour space:Lis lightness,Cis how vivid it is,His the hue angle. Its big advantage is that equal lightness numbers actually *look* equally bright, which makes building consistent palettes far easier than with HSL.
<style>
:root { --brand: #4338ca; }
.base { background: var(--brand); }
/* Auto-generate a darker hover shade by mixing in 25% black */
.hover { background: color-mix(in oklch, var(--brand) 75%, black); }
/* Pick a colour directly in the perceptual oklch space */
.ok { background: oklch(70% 0.15 250); }
.swatch { color:#fff; padding:14px; border-radius:8px; margin-bottom:8px; font-family:sans-serif; }
</style>
<div class="swatch base">Base brand colour</div>
<div class="swatch hover">color-mix() → 25% darker (a ready hover shade)</div>
<div class="swatch ok">oklch(70% 0.15 250)</div>Each swatch shows a modern colour technique:
color-mix(in oklch, var(--brand) 75%, black)— takes the brand colour at 75% strength and blends in 25% black, producing a slightly darker version. This is the trick for deriving a hover shade from one source colour instead of maintaining two.oklch(70% 0.15 250)— names a colour by lightness 70%, chroma 0.15, hue 250° (a blue). Because lightness is perceptual, you can build a whole palette by nudging just the lightness number and the colours stay visually balanced.
Tip: A powerful pattern for design systems: store one --brand variable, then derive hover, active and disabled shades with color-mix(). Change the single brand colour and the whole derived palette updates — no manual recolouring.
Q. What does margin-inline control in a normal English (left-to-right) page?
✍️ Practice
- Replace the physical margins/paddings on a card with
margin-block,margin-inline,padding-blockandpadding-inline. - Define one
--brandcolour and usecolor-mix()to create a darker hover shade for a button.
🏠 Homework
- Convert one component to logical properties, add
dir="rtl"to its wrapper, and confirm it mirrors correctly with no extra CSS.