CSS Nesting (Native)
What Is CSS Nesting?
CSS nesting is a native feature that allows you to write style rules inside other style rules, mirroring the hierarchical structure of your HTML. Instead of repeating the parent selector over and over, you write child rules directly inside the parent block. The browser then computes the full selector by combining the outer and inner selectors automatically. This leads to shorter, more organized, and more maintainable stylesheets.
For over a decade, developers relied on CSS preprocessors like Sass, LESS, and Stylus to get nesting capabilities. These tools compiled nested syntax into flat CSS before sending it to the browser. With native CSS nesting, the browser understands nested rules directly -- no build step, no preprocessor, no compilation. You write nested CSS, and it simply works. This is one of the most significant additions to the CSS language in recent years, fundamentally changing how we author stylesheets.
Native CSS nesting became available in all major browsers starting in 2023. Chrome 112, Firefox 117, and Safari 16.5 all shipped support, making it safe to use in production for the vast majority of users today. In this lesson, you will learn every aspect of CSS nesting: the syntax, the ampersand operator, edge cases, best practices, and how to migrate from preprocessor nesting to native nesting.
A Brief History: Preprocessor Nesting vs Native Nesting
Before native CSS nesting, the only way to nest selectors was through preprocessors. Sass (2006) and LESS (2009) both introduced nesting as a core feature. Here is what preprocessor nesting looks like in Sass:
Sass Nesting (Preprocessor)
/* Sass / SCSS syntax */
.card {
padding: 1.5rem;
background: white;
border-radius: 8px;
.card-header {
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 1rem;
}
.card-body {
color: #555;
line-height: 1.6;
}
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
&--featured {
border-left: 4px solid #3498db;
}
}
/* Sass compiles this to flat CSS: */
.card { padding: 1.5rem; background: white; border-radius: 8px; }
.card .card-header { font-size: 1.25rem; font-weight: bold; margin-bottom: 1rem; }
.card .card-body { color: #555; line-height: 1.6; }
.card:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); }
.card--featured { border-left: 4px solid #3498db; }
Native CSS nesting works similarly but with a few key differences in syntax. The most important difference is when and why you need the & (ampersand) nesting selector. In Sass, the ampersand is only needed when you want to concatenate or attach something directly to the parent selector (like &:hover or &--modifier). In native CSS, the rules about when & is required are slightly different, as we will explore in detail.
Basic Nesting Syntax
The fundamental idea of CSS nesting is simple: you write a rule set inside another rule set. The inner rule is interpreted as a descendant of the outer rule. Let us start with a basic example.
Your First Nested CSS Rule
/* Without nesting (traditional flat CSS) */
.nav { display: flex; gap: 1rem; }
.nav a { color: #333; text-decoration: none; }
.nav a:hover { color: #0066cc; }
/* With native CSS nesting */
.nav {
display: flex;
gap: 1rem;
a {
color: #333;
text-decoration: none;
&:hover {
color: #0066cc;
}
}
}
In the nested version, the a rule is written inside .nav. The browser interprets this as .nav a. The &:hover inside the a block is interpreted as .nav a:hover. Notice how the nesting visually represents the HTML structure, making it easier to understand which styles apply to which elements.
The & (Ampersand) Nesting Selector
The ampersand & is the nesting selector. It explicitly represents the parent selector at the point where it appears. Understanding when to use & and when you can omit it is the most important part of mastering CSS nesting.
When & Is Required
You must use the & nesting selector whenever the nested selector needs to be directly attached to the parent selector without any whitespace. The most common cases are pseudo-classes, pseudo-elements, and compound selectors.
Cases Where & Is Required
/* Pseudo-classes: & attaches directly */
.button {
background: #3498db;
color: white;
padding: 0.75rem 1.5rem;
&:hover {
background: #2980b9;
}
&:focus {
outline: 2px solid #3498db;
outline-offset: 2px;
}
&:active {
transform: translateY(1px);
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
}
/* Computes to: .button:hover, .button:focus, etc. */
/* Pseudo-elements: & attaches directly */
.quote {
position: relative;
padding-left: 1.5rem;
&::before {
content: "\201C";
position: absolute;
left: 0;
font-size: 2rem;
color: #ccc;
}
&::after {
content: "";
display: block;
margin-top: 1rem;
border-bottom: 2px solid #eee;
}
}
/* Computes to: .quote::before, .quote::after */
/* Compound selectors: & combines classes */
.card {
background: white;
&.highlighted {
border: 2px solid gold;
}
&.card--dark {
background: #1a1a2e;
color: white;
}
}
/* Computes to: .card.highlighted, .card.card--dark */
& in &:hover, the browser would interpret it as .button :hover (with a space), which selects any hovered descendant of .button rather than the button itself when hovered. This is a completely different selector with different behavior. The & ensures the pseudo-class attaches directly to the parent selector.When & Is Optional
When nesting with class selectors, ID selectors, attribute selectors, or other selectors that start with a symbol (., #, [), the & is optional. The browser can infer that you mean a descendant selector. However, for type selectors (bare element names like div, p, span), the rules used to be different but have since been relaxed.
Cases Where & Is Optional
/* Class selectors: & is optional */
.sidebar {
width: 300px;
/* Both of these are equivalent */
.sidebar-title { font-weight: bold; }
& .sidebar-title { font-weight: bold; }
/* Both compute to: .sidebar .sidebar-title */
}
/* ID selectors: & is optional */
.page {
#main-content {
max-width: 800px;
margin: 0 auto;
}
/* Computes to: .page #main-content */
}
/* Attribute selectors: & is optional */
.form {
[type="text"] {
border: 1px solid #ccc;
padding: 0.5rem;
}
/* Computes to: .form [type="text"] */
}
/* Universal selector: & is optional */
.container {
* {
box-sizing: border-box;
}
/* Computes to: .container * */
}
Nesting with Type Selectors
Originally, native CSS nesting required the & when nesting type (element) selectors like div, p, h1, or span. This was because the browser parser could not distinguish between a property name and an element name at parse time. However, the specification was updated and browsers now support nesting type selectors without &. This is sometimes called the "relaxed nesting" syntax.
Nesting Type Selectors
/* Modern browsers: type selectors can be nested directly */
.article {
h2 {
font-size: 1.75rem;
color: #333;
margin-bottom: 0.75rem;
}
p {
line-height: 1.8;
margin-bottom: 1rem;
}
ul {
padding-left: 1.5rem;
li {
margin-bottom: 0.5rem;
}
}
img {
max-width: 100%;
height: auto;
border-radius: 8px;
}
}
/* Computes to: .article h2, .article p, .article ul, etc. */
/* You can still use & explicitly if you prefer clarity */
.article {
& h2 { font-size: 1.75rem; }
& p { line-height: 1.8; }
}
/* Same result: .article h2, .article p */
&, some teams choose to always use & for consistency and clarity. This is a style preference. What matters most is that your team agrees on a convention and applies it consistently throughout the codebase.Nesting Pseudo-Classes and Pseudo-Elements
One of the most common uses of nesting is grouping pseudo-classes and pseudo-elements alongside their parent element. This keeps all states and decorations of a component visually together, making the stylesheet much easier to scan and maintain.
Comprehensive Pseudo-Class and Pseudo-Element Nesting
.input-field {
border: 2px solid #ddd;
padding: 0.75rem 1rem;
border-radius: 6px;
transition: border-color 0.2s, box-shadow 0.2s;
&:hover {
border-color: #999;
}
&:focus {
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
outline: none;
}
&:focus-visible {
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.4);
}
&::placeholder {
color: #aaa;
font-style: italic;
}
&:valid {
border-color: #2ecc71;
}
&:invalid:not(:placeholder-shown) {
border-color: #e74c3c;
}
&:disabled {
background: #f5f5f5;
color: #999;
cursor: not-allowed;
}
&:read-only {
background: #fafafa;
border-style: dashed;
}
}
/* Complex pseudo selectors */
.list {
&:first-child { margin-top: 0; }
&:last-child { margin-bottom: 0; }
&:nth-child(odd) { background: #f9f9f9; }
&:not(:last-child) { border-bottom: 1px solid #eee; }
&:empty { display: none; }
&::marker {
color: #3498db;
font-weight: bold;
}
}
Nesting Media Queries Inside Selectors
One of the most powerful features of CSS nesting is the ability to write @media queries directly inside a selector block. This keeps all the styles for a component -- including its responsive variations -- in one place rather than scattered across separate media query blocks at the bottom of the file.
Nesting @media Queries Inside Selectors
/* Traditional approach: media queries separate from component */
.hero {
padding: 2rem;
text-align: center;
}
.hero h1 {
font-size: 2rem;
}
@media (min-width: 768px) {
.hero {
padding: 4rem;
}
.hero h1 {
font-size: 3rem;
}
}
@media (min-width: 1200px) {
.hero {
padding: 6rem;
}
.hero h1 {
font-size: 4rem;
}
}
/* Nested approach: everything together */
.hero {
padding: 2rem;
text-align: center;
@media (min-width: 768px) {
padding: 4rem;
}
@media (min-width: 1200px) {
padding: 6rem;
}
h1 {
font-size: 2rem;
@media (min-width: 768px) {
font-size: 3rem;
}
@media (min-width: 1200px) {
font-size: 4rem;
}
}
}
Notice how the nested version keeps all .hero styles in one block. You can immediately see every breakpoint variation without scrolling through the file. This is a significant improvement for maintainability, especially in large stylesheets with dozens of components.
Nesting Other At-Rules
/* You can nest other at-rules too */
.card {
background: white;
color: #333;
/* Dark mode */
@media (prefers-color-scheme: dark) {
background: #1a1a2e;
color: #e0e0e0;
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
transition: none;
animation: none;
}
/* Print styles */
@media print {
box-shadow: none;
border: 1px solid #ccc;
}
/* Container queries (also nestable) */
@container sidebar (min-width: 300px) {
flex-direction: row;
gap: 1rem;
}
}
Deep Nesting and Readability Concerns
Just because you can nest deeply does not mean you should. One of the most common mistakes with CSS nesting -- whether in preprocessors or native CSS -- is nesting too deeply. Deep nesting leads to overly specific selectors, makes code harder to read, and creates tightly coupled styles that are difficult to override or reuse.
The Problem with Deep Nesting
/* BAD: Too deeply nested -- hard to read and overly specific */
.page {
.main-content {
.article {
.article-body {
.paragraph {
.link {
color: blue;
&:hover {
color: darkblue;
}
}
}
}
}
}
}
/* Generates: .page .main-content .article .article-body .paragraph .link */
/* This selector is extremely specific and nearly impossible to override */
/* GOOD: Keep nesting shallow -- max 3 levels */
.article-body {
.link {
color: blue;
&:hover {
color: darkblue;
}
}
}
Here are the practical problems with deep nesting:
- High specificity -- Deeply nested selectors have high specificity, making them hard to override without resorting to
!important. - Fragile selectors -- The styles break if you change the HTML structure, because every nesting level maps to a DOM relationship.
- Poor readability -- Deeply indented code is harder to scan and understand at a glance.
- Large file output -- Each level of nesting repeats the parent selectors, leading to longer generated selectors and larger CSS files.
Refactoring Deep Nesting
/* Before: deeply nested */
.sidebar {
.widget {
.widget-header {
.widget-title {
font-size: 1rem;
}
}
.widget-body {
.widget-list {
.widget-item {
padding: 0.5rem;
}
}
}
}
}
/* After: flatter with descriptive class names */
.widget {
&-header {
/* note: this creates ".widget -header" not ".widget-header" */
/* For BEM, see the section below */
}
}
/* Better: flat selectors with clear class names */
.widget-title {
font-size: 1rem;
}
.widget-item {
padding: 0.5rem;
}
Nesting with Combinators
CSS nesting works with all CSS combinators: child (>), adjacent sibling (+), general sibling (~), and column (||). These combinators let you express precise DOM relationships within your nested rules.
Using Combinators in Nested Rules
/* Child combinator */
.nav {
> li {
display: inline-block;
margin-right: 1rem;
> a {
color: #333;
text-decoration: none;
}
}
}
/* Computes to: .nav > li, .nav > li > a */
/* Adjacent sibling combinator */
.heading {
+ p {
font-size: 1.125rem;
color: #555;
margin-top: 0.5rem;
}
}
/* Computes to: .heading + p */
/* General sibling combinator */
.toggle-checkbox:checked {
~ .toggle-content {
display: block;
opacity: 1;
}
~ .toggle-label {
color: #3498db;
}
}
/* Computes to: .toggle-checkbox:checked ~ .toggle-content, etc. */
/* Combining nesting with combinators */
.form-group {
margin-bottom: 1.5rem;
> label {
display: block;
font-weight: 600;
margin-bottom: 0.5rem;
}
> input {
width: 100%;
padding: 0.75rem;
}
+ .form-group {
border-top: 1px solid #eee;
padding-top: 1.5rem;
}
}
Specificity in Nested Rules
Understanding how specificity works with nested rules is crucial. Native CSS nesting computes specificity by combining the outer and inner selectors just as if you had written them flat. The nesting selector & carries the specificity of the outer selector it represents.
Specificity of Nested Selectors
/* The specificity of nested rules is computed as the full selector */
/* Specificity: (0, 1, 0) for .card */
.card {
background: white;
/* Specificity: (0, 1, 1) for .card h2 */
h2 {
color: #333;
}
/* Specificity: (0, 2, 0) for .card.featured */
&.featured {
border: 2px solid gold;
}
/* Specificity: (0, 2, 0) for .card:hover */
&:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
/* Specificity: (0, 2, 0) for .card .card-title */
.card-title {
font-size: 1.25rem;
}
}
/* Important: nesting does NOT add extra specificity beyond
what the full flat selector would have. These are equivalent: */
/* Flat: specificity (0, 2, 0) */
.card .card-title { font-size: 1.25rem; }
/* Nested: also specificity (0, 2, 0) */
.card {
.card-title { font-size: 1.25rem; }
}
/* The & selector itself has the specificity of its outer selector */
/* When & is used inside :is(), :not(), or :has(),
it takes the specificity of the most specific argument */
& when the outer selector is a selector list. If the outer selector is .foo, #bar, then & inside a nested rule is treated as :is(.foo, #bar), which takes the highest specificity of the list. In this case, that would be (1, 0, 0) from #bar, even when the rule is applied to elements matching .foo. This matches the behavior of :is() specificity.The & Selector in Different Positions
The & nesting selector is not limited to the beginning of the nested selector. You can place it anywhere to create different selector relationships. This is extremely useful for creating context-dependent styles.
Placing & in Different Positions
/* & at the start (most common) */
.button {
&:hover { background: #2980b9; }
/* .button:hover */
}
/* & at the end -- reverses the relationship */
.button {
.dark-theme & {
background: #444;
color: white;
}
/* .dark-theme .button */
}
/* This is incredibly useful for theming */
.card {
background: white;
color: #333;
.theme-dark & {
background: #2d2d2d;
color: #f0f0f0;
}
.theme-high-contrast & {
border: 2px solid black;
color: black;
background: white;
}
[dir="rtl"] & {
text-align: right;
}
}
/* Generates:
.theme-dark .card { ... }
.theme-high-contrast .card { ... }
[dir="rtl"] .card { ... } */
/* & in the middle */
.icon {
width: 24px;
height: 24px;
.button & {
width: 16px;
height: 16px;
}
/* .button .icon */
}
/* Multiple & in one selector */
.item {
& + & {
margin-top: 1rem;
}
/* .item + .item */
}
Migrating from Sass to Native CSS Nesting
If your project currently uses Sass or LESS for nesting, migrating to native CSS nesting is straightforward in most cases. However, there are some differences you need to be aware of.
Key Differences Between Sass and Native Nesting
/* DIFFERENCE 1: String concatenation with & does NOT work */
/* Sass: & concatenates strings */
.block {
&__element { color: red; } /* .block__element */
&--modifier { color: blue; } /* .block--modifier */
}
/* Native CSS: & does NOT concatenate strings */
.block {
&__element { color: red; } /* This does NOT work as expected! */
/* The browser sees this as: .block __element (invalid) */
}
/* Native CSS solution for BEM-like patterns */
.block {
/* Use full class names instead */
}
.block__element { color: red; }
.block--modifier { color: blue; }
/* Or nest with the full selector */
.block {
color: black;
}
.block__element {
color: red;
}
/* DIFFERENCE 2: @extend does not exist in native CSS */
/* Sass: @extend */
.error { color: red; }
.critical-error {
@extend .error;
font-weight: bold;
}
/* Native CSS: no @extend -- use class composition in HTML instead */
/* DIFFERENCE 3: Variables */
/* Sass: $variables */
$primary: #3498db;
.button { color: $primary; }
/* Native CSS: custom properties */
.button { color: var(--primary); }
/* DIFFERENCE 4: Native CSS nesting specificity can differ slightly */
/* Sass generates flat selectors, native nesting may use :is() internally */
& does not support string concatenation. In Sass, &__element concatenates the parent selector with __element to produce .block__element. In native CSS, & is a selector that represents the parent, not a string that gets concatenated. This means BEM-style naming with & does not work the same way in native CSS.Practical Example: Component Styling with Nesting
Let us build a real-world component using native CSS nesting to see how it organizes code in practice.
Building a Card Component with Nesting
.pricing-card {
background: white;
border-radius: 12px;
padding: 2rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
transition: transform 0.2s, box-shadow 0.2s;
&:hover {
transform: translateY(-4px);
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
}
&.popular {
border: 2px solid #3498db;
position: relative;
&::before {
content: "Most Popular";
position: absolute;
top: -12px;
left: 50%;
transform: translateX(-50%);
background: #3498db;
color: white;
padding: 0.25rem 1rem;
border-radius: 20px;
font-size: 0.75rem;
font-weight: bold;
text-transform: uppercase;
}
}
header {
text-align: center;
padding-bottom: 1.5rem;
border-bottom: 1px solid #eee;
h3 {
font-size: 1.25rem;
color: #333;
margin-bottom: 0.5rem;
}
.price {
font-size: 2.5rem;
font-weight: 800;
color: #3498db;
span {
font-size: 1rem;
font-weight: 400;
color: #999;
}
}
}
ul {
list-style: none;
padding: 1.5rem 0;
li {
padding: 0.5rem 0;
color: #555;
&::before {
content: "\2713";
color: #2ecc71;
margin-right: 0.75rem;
font-weight: bold;
}
+ li {
border-top: 1px solid #f5f5f5;
}
}
}
.cta-button {
display: block;
width: 100%;
padding: 0.875rem;
border: none;
border-radius: 8px;
background: #3498db;
color: white;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: background 0.2s;
&:hover {
background: #2980b9;
}
&:focus-visible {
outline: 2px solid #3498db;
outline-offset: 2px;
}
}
@media (min-width: 768px) {
padding: 2.5rem;
header .price {
font-size: 3rem;
}
}
@media (prefers-color-scheme: dark) {
background: #1e1e2e;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
header {
border-bottom-color: #333;
h3 {
color: #e0e0e0;
}
}
ul li {
color: #ccc;
+ li {
border-top-color: #333;
}
}
}
}
BEM with Native Nesting
Block Element Modifier (BEM) is a popular CSS naming methodology. Since native CSS nesting does not support string concatenation with &, you need a different approach than what Sass developers are used to.
BEM Patterns with Native CSS Nesting
/* Approach 1: Nest elements within the block */
.card {
background: white;
border-radius: 8px;
overflow: hidden;
.card__header {
padding: 1rem 1.5rem;
border-bottom: 1px solid #eee;
}
.card__title {
font-size: 1.25rem;
font-weight: bold;
}
.card__body {
padding: 1.5rem;
}
.card__footer {
padding: 1rem 1.5rem;
background: #f9f9f9;
}
}
/* Approach 2: Flat blocks with nested modifiers and states */
.card {
background: white;
}
.card__header {
padding: 1rem 1.5rem;
}
.card__body {
padding: 1.5rem;
/* Nest modifiers inside elements */
&--compact {
/* CAUTION: This does NOT create .card__body--compact */
/* It creates .card__body --compact (with space) which is invalid */
}
}
/* Approach 3: The recommended approach for BEM + native nesting */
/* Keep blocks and elements flat, use nesting for states and responsive */
.card {
background: white;
&:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); }
@media (min-width: 768px) {
display: grid;
grid-template-columns: 1fr 2fr;
}
}
.card__header {
padding: 1rem 1.5rem;
&:first-child { padding-top: 1.5rem; }
}
.card--featured {
border: 2px solid gold;
background: #fffdf0;
}
Browser Support
Native CSS nesting is supported in all modern evergreen browsers. Here is the support timeline:
- Chrome / Edge -- Version 112+ (April 2023). Relaxed nesting (bare type selectors) from Chrome 120+.
- Firefox -- Version 117+ (August 2023). Relaxed nesting from Firefox 120+.
- Safari -- Version 16.5+ (May 2023). Relaxed nesting from Safari 17.2+.
As of early 2025, CSS nesting has well over 90% global browser support. For the small percentage of users on older browsers, nested rules will simply be ignored -- the styles will not apply, but nothing will break. You can use @supports to provide fallbacks if needed.
Progressive Enhancement with @supports
/* Fallback: flat CSS for older browsers */
.nav a { color: #333; }
.nav a:hover { color: #0066cc; }
/* Enhanced: nested CSS for modern browsers */
@supports selector(&) {
.nav {
a {
color: #333;
&:hover {
color: #0066cc;
}
}
}
}
/* In practice, you usually do not need the @supports check
because the flat CSS provides a baseline and the nested
CSS just overrides it with the same result */
Best Practices and Anti-Patterns
After working with CSS nesting in real projects, several best practices have emerged. Following these will keep your nested code clean, performant, and maintainable.
Best Practices
CSS Nesting Best Practices
/* 1. Keep nesting shallow -- max 3 levels */
.card {
header {
h3 { /* This is level 3 -- stop here */ }
}
}
/* 2. Use nesting for component scoping */
.search-form {
display: flex;
gap: 0.5rem;
input {
flex: 1;
padding: 0.75rem;
}
button {
padding: 0.75rem 1.5rem;
background: #3498db;
color: white;
}
}
/* 3. Nest media queries inside components */
.sidebar {
width: 100%;
@media (min-width: 768px) {
width: 300px;
position: sticky;
top: 2rem;
}
}
/* 4. Group pseudo-classes and pseudo-elements with their element */
.link {
color: #333;
text-decoration: none;
&:hover { color: #0066cc; }
&:focus-visible { outline: 2px solid #0066cc; }
&:active { color: #004499; }
&::after { content: " \2192"; }
}
/* 5. Use & for context-dependent styles */
.icon {
width: 24px;
height: 24px;
.button & { width: 18px; height: 18px; }
.heading & { width: 28px; height: 28px; }
}
Anti-Patterns to Avoid
Common CSS Nesting Mistakes
/* ANTI-PATTERN 1: Nesting everything */
/* Do not nest rules just because you can */
body {
main {
.content {
.article {
p {
a {
color: blue; /* 6 levels deep -- terrible! */
}
}
}
}
}
}
/* ANTI-PATTERN 2: Over-qualifying selectors */
.card {
.card-header {
.card-title {
/* .card .card-header .card-title is overly specific */
/* .card-title alone would work fine */
}
}
}
/* ANTI-PATTERN 3: Expecting Sass-style concatenation */
.block {
&__element { } /* Does NOT create .block__element */
&--modifier { } /* Does NOT create .block--modifier */
}
/* ANTI-PATTERN 4: Nesting unrelated selectors together */
.button {
background: blue;
/* This unrelated selector should not be nested here */
.footer-links {
display: flex;
}
}
/* ANTI-PATTERN 5: Duplicating properties across nesting levels */
.card {
color: #333; /* Set here */
h2 {
color: #333; /* Redundant -- inherits from parent */
}
}
Exercise 1: Refactor Flat CSS to Nested CSS
Take the following flat CSS and refactor it using native CSS nesting. Keep the nesting to a maximum of 3 levels. Group all pseudo-classes and pseudo-elements with their parent element. Nest the media query inside the component block. The flat CSS is: .navbar { display: flex; align-items: center; padding: 1rem 2rem; background: white; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }, .navbar .logo { font-size: 1.5rem; font-weight: bold; color: #333; }, .navbar .nav-links { display: flex; gap: 1.5rem; margin-left: auto; }, .navbar .nav-links a { color: #555; text-decoration: none; padding: 0.5rem 0; border-bottom: 2px solid transparent; }, .navbar .nav-links a:hover { color: #3498db; border-bottom-color: #3498db; }, .navbar .nav-links a.active { color: #3498db; font-weight: 600; border-bottom-color: #3498db; }, @media (max-width: 768px) { .navbar { flex-direction: column; padding: 1rem; } .navbar .nav-links { margin-left: 0; margin-top: 1rem; } }. Ensure your nested version produces exactly the same computed selectors and styles as the flat version.
Exercise 2: Build a Themed Component with Nesting
Create a .profile-card component using native CSS nesting that supports three color themes: default (light), .theme-dark, and .theme-ocean. The card should have a header with an avatar, name, and role; a body with a bio paragraph; and a footer with social links. Use the & selector in different positions: at the start for pseudo-classes and compound selectors, at the end for theme context (.theme-dark &), and in the middle for sibling relationships (& + &). Nest @media queries for responsive breakpoints at 480px and 768px inside the component. Add :hover, :focus-visible, and ::before nested rules for the social links. Keep all nesting to 3 levels maximum. Finally, add a nested @media (prefers-color-scheme: dark) query that applies dark styles when no explicit theme class is set.