TL;DR: Native CSS nesting is here – and it makes Sass obsolete for the most common use case (nesting selectors). All modern browsers support it. Time to simplify your build setup.

🤔 What Even Is CSS Nesting?

If you've ever used Sass or SCSS, you know the drill: nesting selectors inside each other to mirror your HTML structure in CSS. For years, that was the reason many developers reached for a preprocessor in the first place.

And now? Now CSS can do it natively. No compiler, no build step, no node_modules folder full of Sass dependencies. Just write CSS and it works.

📝 The Basics – What It Looks Like

The concept is simple: you write your child selectors directly inside the parent selector. Exactly like Sass.

.card {
  background: white;
  border-radius: 8px;

  .card-title {
    font-size: 1.5rem;
    font-weight: bold;
  }

  .card-body {
    padding: 1rem;
    line-height: 1.6;
  }
}

That's it. No special setup needed. Your browser just gets it.

🔗 The & Selector – Your Best Friend

Just like in Sass, native CSS has the & selector. It references the outer selector and is especially useful for pseudo-classes, pseudo-elements, and compound selectors.

.button {
  background: #3b82f6;
  color: white;
  transition: background 0.2s;

  &:hover {
    background: #2563eb;
  }

  &:focus-visible {
    outline: 2px solid #3b82f6;
    outline-offset: 2px;
  }

  &.button--large {
    padding: 1rem 2rem;
    font-size: 1.25rem;
  }

  &::after {
    content: " →";
  }
}

Quick note: for pseudo-classes and pseudo-elements, the & is actually optional – you can write :hover { } directly. But explicit beats implicit, right?

📏 Nesting Rules – What Works and What Doesn't

There are a few rules you should know:

Element selectors needed & or a relative syntax. You couldn't just write div { } inside a selector. Instead:

.container {
  /* This works: */
  & div {
    margin: 1rem;
  }

  /* With relaxed parsing (since 2024): */
  div {
    margin: 1rem;
  }
}

The so-called "relaxed nesting syntax" now allows bare element selectors in all modern browsers. Originally this wasn't possible – a leftover from the initial spec.

Deep nesting? Sure thing!

.page {
  .sidebar {
    .nav-item {
      color: gray;

      &:hover {
        color: black;
      }
    }
  }
}

But don't go overboard. Three levels deep is usually the max before your CSS becomes unreadable.

📱 Media Queries Inside Nesting

This is where it gets really exciting. You can nest media queries directly inside your selector. No more jumping back and forth between selectors and media queries!

.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;

  @media (min-width: 768px) {
    grid-template-columns: repeat(2, 1fr);
  }

  @media (min-width: 1024px) {
    grid-template-columns: repeat(3, 1fr);
  }
}

For me personally, this is the biggest game changer. All styles for an element in one place. Brilliant.

⚔️ Sass Nesting vs. Native CSS Nesting – The Differences

At first glance, everything looks the same. But there are some subtle differences you should be aware of:

FeatureSass/SCSSNative CSS
String concatenation (&__element)✅ Yes❌ No
Nesting element selectors✅ Direct✅ Relaxed syntax (since 2024)
Nesting media queries✅ Yes✅ Yes
Variables$varvar(--custom)
Mixins/Functions✅ Yes❌ No (yet)
Build step required✅ Always❌ Never
Specificity behaviorFlat (compiled)Nested (like :is())

The biggest gotcha: in Sass, &__element compiles to .block__element. In native CSS, this does not work. The & is a real selector replacement, not string concatenation. If you're using BEM, you'll need to rethink your approach.

Also: specificity in native nesting behaves as if you were using :is(). This can lead to different results compared to compiled Sass in edge cases.

🪦 @nest – Short-Lived and Already Buried

If you've heard about the @nest rule: forget it. It was part of an early draft of the spec and was never implemented in browsers. Instead, we got the "relaxed nesting syntax," which is far more elegant.

The short version: previously, you had to explicitly prepend & for certain selectors. Today, that's optional in most cases.

🚀 Combined with Modern CSS – This Is Where It Gets Powerful

Native CSS nesting really shines when combined with other modern CSS features.

With CSS Variables

.theme-dark {
  --bg: #1a1a2e;
  --text: #e0e0e0;
  --accent: #e94560;

  .card {
    background: var(--bg);
    color: var(--text);

    .card-link {
      color: var(--accent);

      &:hover {
        opacity: 0.8;
      }
    }
  }
}
CSS variables: Flexible styling for your components 🎨
Learn how to use CSS Custom Properties for flexible and maintainable styling.

With :has() – The "Parent Selector"

.form-group {
  border: 1px solid #ccc;

  &:has(input:invalid) {
    border-color: red;

    .error-message {
      display: block;
    }
  }

  &:has(input:focus) {
    border-color: #3b82f6;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
  }
}

With Container Queries

.widget {
  container-type: inline-size;

  .widget-content {
    display: flex;
    flex-direction: column;

    @container (min-width: 400px) {
      flex-direction: row;
    }
  }
}

See the pattern? Everything that belongs to an element lives in one place. This is the dream of component-based CSS – without a JavaScript framework.

Tailwind CSS vs. Vanilla CSS – When Is Which Worth It?
A comparison of Tailwind CSS and Vanilla CSS – and when each approach makes sense.

🔄 Migration Guide: Dropping Sass Nesting

Want to ditch Sass when you're only using it for nesting? Here's your plan:

1. Identify your Sass features. Are you really only using nesting? Or also mixins, functions, loops? If so, you probably still need Sass.

2. Replace &__element patterns. BEM concatenation doesn't work in native CSS. Write out the selectors:

/* Sass */
.block {
  &__element { color: red; }
  &--modifier { color: blue; }
}

/* Native CSS */
.block {
  .block__element { color: red; }
  .block--modifier { color: blue; }
}

3. Rename your files. From .scss to .css. Remove Sass-specific syntax like $variables and replace them with CSS Custom Properties.

4. Remove the Sass compiler. From your package.json, your Webpack/Vite config, everywhere.

5. Test thoroughly. Specificity might change. Watch out for edge cases.

🌐 Browser Support

The good news: native CSS nesting is supported by all modern browsers.

Chrome 120+, Firefox 117+, Safari 17.2+, and Edge 120+ are all on board. That covers over 90% of users. The relaxed nesting syntax (no & needed for element selectors) has been available everywhere since mid-2024.

CSS Nesting | Can I use...
Browser support tables for CSS Nesting across desktop and mobile browsers.

If you still need to support older browsers: the PostCSS Nesting Plugin can compile native nesting into flat CSS. Use the syntax today and stay compatible.

CSS nesting - CSS | MDN
The CSS nesting module defines a syntax for nesting selectors, providing the ability to nest one style rule inside another.

💡 Conclusion

Native CSS nesting is no longer an experiment – it's production-ready. If you've been using Sass just for nesting, there's no reason to keep it around. Your CSS gets simpler, your builds get faster, and your dependencies get fewer.

Sure, Sass still has its place for complex projects with mixins, functions, and loops. But for most projects, modern CSS is more than enough. And that's a good thing.

So go ahead. Nest away. Your bundler will thank you. 🚀

Artikel teilen:Share article:

Discover more articles

Natives CSS Nesting – Schluss mit Sass nur fürs Verschachteln 🪺
Previous article

Natives CSS Nesting – Schluss mit Sass nur fürs Verschachteln 🪺

TL;DR: Natives CSS Nesting ist da – und es macht Sass für den häufigsten Anwendungsfall (Verschachteln von Selektoren) überflüssig. Alle modernen Browser unterstützen es. Zeit, dein Build-Setup zu vereinfachen. 🤔 Was ist CSS Nesting überhaupt? Wenn du jemals Sass oder SCSS benutzt hast, kennst du das: Selektoren ineinander verschachteln, um die

5 min read 19. Mai 2026
CSS Scroll-Driven Animations – No JavaScript Required 🎬
Similar article

CSS Scroll-Driven Animations – No JavaScript Required 🎬

TL;DR: CSS Scroll-Driven Animations let you animate elements based on scroll position – entirely without JavaScript. With animation-timeline: scroll() and animation-timeline: view(), you can build progress bars, fade-ins, and parallax effects in pure CSS. Performant, elegant, and future-proof. 🤔 What Are Scroll-Driven Animations? Imagine scrolling through a website and elements move,

5 min read 17. Mai 2026
CSS Grid: The Missing Counterpart to Flexbox 🧩
Similar article

CSS Grid: The Missing Counterpart to Flexbox 🧩

TL;DR: CSS Grid is the missing puzzle piece to your Flexbox knowledge. While Flexbox handles one-dimensional layouts, Grid gives you full control over rows AND columns simultaneously. This article covers everything from basics to subgrid – with practical examples you can use right away. You know Flexbox? Great. Time to

4 min read 15. Mai 2026
View Transitions API: Smooth Page Transitions Without a Framework ✨
Similar article

View Transitions API: Smooth Page Transitions Without a Framework ✨

TL;DR: The View Transitions API brings buttery-smooth page transitions directly to the browser - no framework, no JavaScript library needed. Just CSS and a few lines of JS. Here's how it works and why you should start using it today. 🤔 What Are View Transitions Anyway? You know

6 min read 13. Mai 2026
CSS :has() – The Parent Selector Everyone’s Been Waiting For 🎯
Similar article

CSS :has() – The Parent Selector Everyone’s Been Waiting For 🎯

TL;DR: CSS :has() is the long-awaited parent selector – you can finally style parent elements based on their children. No more JavaScript hacks, no workarounds, just pure CSS. And yes, it works in all modern browsers. 🤔 Why CSS Never Had a Parent Selector If you've been writing CSS

4 min read 27. Apr. 2026