Two newer CSS features change how everyday stylesheets look. The first is native nesting. For years, developers used preprocessors such as Sass just to write rules inside other rules, keeping a component's styles together. Now browsers understand nesting directly, so you can write .card { & h3 { ... } } in plain CSS with no build step.
The second is logical properties. Properties like margin-left and padding-top are tied to physical directions. But in Arabic and Hebrew, text runs right to left, and in some Japanese and Chinese layouts it runs top to bottom. Logical properties such as margin-inline-start and padding-block describe directions relative to the text instead, so one stylesheet works in every language.
In this lesson you'll learn how nesting works, the role of the & symbol, nesting media queries inside rules, and how nesting affects specificity. Then you'll meet the logical property names and shorthands such as margin-inline: auto and inset: 0, which are worth using even on English-only sites because they're shorter.
Native CSS nesting
.card {
padding: 16px;
& h3 { margin: 0; } /* .card h3 */
&:hover { background: #f9fafb; } /* .card:hover */
&.featured { border-color: gold; } /* .card.featured */
.dark & { background: #111; } /* .dark .card */
}&stands for the parent selector.& h3means "an h3 inside .card", and&:hovermeans ".card when hovered".- Without a space,
&.featuredjoins the selectors: the card that also has the featured class. - Putting
&at the end, as in.dark &, matches the card inside a.darkancestor. - For a nested descendant you can leave out
&and just writeh3 { ... }; all modern browsers support it.
Nesting media and container queries
Nesting really pays off with at-rules. The responsive behaviour lives next to the styles it changes:
.grid {
display: grid;
gap: 12px;
@media (min-width: 700px) {
grid-template-columns: 1fr 1fr;
}
}Inside a nested @media, declarations apply to the parent selector, so you don't repeat .grid. The same works for @container and @supports.
Nesting and specificity
A nested selector is treated like :is() around the parent. .card { & h3 {} } has the same specificity as .card h3. If the parent is a list, such as #main, .side { & a {} }, the parent part takes the highest specificity in that list, which can surprise you.
Keep nesting shallow: two or three levels at most. Deep nesting creates long, highly specific selectors that are hard to override, the same problem Sass users learned to avoid.
Logical properties
| Physical | Logical | In English (left to right, top to bottom) |
|---|---|---|
margin-left / margin-right | margin-inline-start / margin-inline-end | left / right |
margin-left + margin-right | margin-inline | both sides |
padding-top + padding-bottom | padding-block | top and bottom |
width / height | inline-size / block-size | width / height |
top, right, bottom, left | inset-block-start, inset-inline-end... | positions |
border-left | border-inline-start | left border |
text-align: left | text-align: start | left |
Inline is the direction text flows along a line; block is the direction lines stack. In a right-to-left language, margin-inline-start becomes the right margin automatically.
CSS Nesting Syntax
Nesting and logical properties
.button {
padding-block: 10px;
padding-inline: 18px;
&:hover { filter: brightness(1.1); }
& .icon { margin-inline-end: 6px; }
@media (min-width: 600px) { padding-inline: 24px; }
}
.wrap { max-inline-size: 70ch; margin-inline: auto; }
.overlay { position: absolute; inset: 0; }CSS Nesting Summary
- Native CSS nesting lets you write rules inside rules, with no preprocessor.
&represents the parent selector;&:hoverand&.classjoin to it.- Media and container queries can be nested inside a rule.
- Keep nesting shallow to avoid overly specific selectors.
- Logical properties like
margin-inlineandpadding-blockadapt to the writing direction.
CSS Nesting Examples
Each example runs in the page. Edit the code and press Run to see what changes.
A nested card component
<article class="card">
<h3>Mountain cabin</h3>
<p>Sleeps four. Wood stove, lake views.</p>
<a href="#">View dates</a>
</article>
<article class="card featured">
<h3>Beach house</h3>
<p>Steps from the sand.</p>
<a href="#">View dates</a>
</article>.card {
max-inline-size: 320px;
padding: 16px;
margin-block-end: 12px;
border: 2px solid #e2e8f0;
border-radius: 12px;
font-family: sans-serif;
& h3 { margin: 0 0 6px; }
& p { margin: 0 0 10px; color: #475569; }
& a { color: #2563eb; font-weight: 600; }
&:hover { border-color: #94a3b8; }
&.featured { border-color: #f59e0b; background: #fffbeb; }
}Line-by-line explanation
- Lines 2 to 4Logical size and margin properties.
- Lines 9 to 11Child styles live inside the component.
- Line 13
&:hovermeans.card:hover. - Line 14
&.featuredmeans a card that also has the featured class.
Nested media queries
Drag the panel wider than 600px.
<ul class="features">
<li>Fast setup</li>
<li>Works offline</li>
<li>Private by design</li>
</ul>.features {
display: grid;
gap: 10px;
padding: 0;
list-style: none;
font: 600 15px sans-serif;
& li {
padding-block: 14px;
padding-inline: 16px;
background: #ecfeff;
border-inline-start: 4px solid #0891b2;
}
@media (min-width: 600px) {
grid-template-columns: repeat(3, 1fr);
}
}Line-by-line explanation
- Lines 8 to 13Each item gets padding and an accent border on its starting edge.
- Lines 15 to 17The media query sits inside the rule, so it applies to
.featureswithout repeating it.
Logical properties in right-to-left text
The same CSS in an English and an Arabic block. The accent border and padding flip automatically.
<p class="note" dir="ltr">Delivery takes two to three days.</p>
<p class="note" dir="rtl">يستغرق التوصيل يومين إلى ثلاثة أيام.</p>.note {
border-inline-start: 4px solid #16a34a;
padding-inline-start: 12px;
padding-block: 8px;
margin-inline: 0 40px;
background: #f0fdf4;
text-align: start;
font-family: sans-serif;
}Line-by-line explanation
- Lines 2 to 3The border and padding are on the starting edge: left in English, right in Arabic.
- Line 5The 40px end margin flips side too.
- Line 7
startaligns text to the start of the line in either direction.
Common CSS Nesting Mistakes
Forgetting & for pseudo-classes
.btn {
:hover { color: red; } /* means .btn :hover, any hovered descendant */
}.btn {
&:hover { color: red; }
}Nesting too deep
.page { .main { .content { .post { .title { a { color: blue; } } } } } }.post-title a { color: blue; }Deep nesting produces long, highly specific selectors.
Mixing physical and logical for the same edge
.box { margin-left: 20px; margin-inline-start: 0; } /* confusing; both set the left edge in English */.box { margin-inline-start: 20px; }Pick one style for a property and stick with it.
CSS Nesting in Real Projects
Where you'll see them
Since 2023, nesting has been supported in every major browser, and many teams have dropped Sass just for nesting. Frameworks such as Tailwind CSS v4 generate logical properties, and sites translated into Arabic, Hebrew or Persian rely on them to flip layouts with a single dir="rtl". Logical shorthands like inset: 0 and margin-inline: auto now appear in most modern codebases.
CSS Nesting Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Style the card's hover state inside the nested rule.
.card {
:hover { box-shadow: 0 4px 12px rgb(0 0 0 / 0.1); }
}
& refers to .card.What does & h3 mean inside .card { }?
Which logical property sets top and bottom padding?
What does .dark & match when nested inside .card?
The button should turn green on hover (not its children), and use logical padding of 10px top and bottom and 20px start and end. Fix it.
<button class="b">Go</button>.b {
padding-left: 20px;
:hover { background: rgb(22, 163, 74); }
}- Block padding is 10px
- Inline padding is 20px
- Hover uses &
CSS Nesting Quiz
5 questions to check what you learned.
Do you need Sass to nest CSS today?
- No, modern browsers support native nesting
- Yes, always
- Only for media queries
- Only in Chrome
In a left-to-right language, what is margin-inline-end?
- The top margin
- The left margin
- The bottom margin
- The right margin
What does inset: 0 do?
- Removes padding
- Sets top, right, bottom and left to 0
- Adds an inner shadow
- Resets margins
Why keep nesting shallow?
- Browsers limit it to two levels
- It makes CSS slower to download
- Nested rules can't use classes
- Deep nesting creates long, highly specific selectors that are hard to override
Inside a nested @media block, which element do bare declarations apply to?
- body
- Every element
- The parent rule's selector
- None, they're ignored
CSS Nesting Challenge
A nested, logical alert
- Give
.alertpadding-block: 12px,padding-inline: 16pxandborder-inline-start: 4px solid rgb(37, 99, 235) - Inside
.alert, nest a rule so.alert.errorhas aborder-inline-start-colorofrgb(220, 38, 38) - Inside
.alert, nest a rule so itsstrongchildren havemargin-inline-end: 6px - Inside
.alert, nest a media query so frommin-width: 600pxthepadding-inlineis24px
<p class="alert" id="a1"><strong>Note</strong> Your order has shipped.</p>
<p class="alert error" id="a2"><strong>Error</strong> Payment failed.</p>.alert {
font-family: sans-serif;
}- Logical padding and border
- Error variant is red
- Strong has an end margin
- Nested media query