Native CSS Nesting in Tailwind v4: Using Nested Selectors the Right Way
AI generated
tw
Tailwind CSS · CSS Nesting · Tailwind v4 · Build Tools
Native CSS Nesting in Tailwind v4
nested selectors without a preprocessor

With Tailwind v4, native CSS nesting officially enters the workflow through the new Rust-based engine. Developers coming from years of Sass nesting need to adjust a few habits, but gain a technique that runs directly in the browser with no preprocessor at all.

14 min read Native CSS Nesting · & Selector Tailwind v4 · Oxide Engine

1. Why CSS nesting matters for utility-first developers

Anyone working consistently utility-first writes very little custom CSS, because classes are combined directly in the markup. Still, there are situations where custom CSS is unavoidable, for example complex pseudo-element chains, integrating third-party widgets whose markup you don't control, or recurring compositions of many utility classes bundled into a named class through @apply. In exactly these edge cases, CSS nesting used to be strictly a Sass or PostCSS affair that required an extra build step.

With native CSS nesting joining the CSS specification and gaining broad browser support, that dependency disappears. Tailwind v4 leans into this by having its new build engine understand native nesting directly, flattening it for older target environments only where necessary. For developers, that means nested selectors can be written in custom CSS files without a separate Sass compiler hanging off the build pipeline, which slims down the toolchain and cuts build times.

2. Native CSS nesting basics: the & selector

Native CSS nesting lets you write a rule directly inside another rule, with the ampersand acting as a placeholder for the enclosing selector. A rule like .card { & p { margin: 0; } } is exactly equivalent to the flat form .card p { margin: 0; }, except the relationship between the two selectors is visible right in the source instead of being expressed across two separate, potentially far-apart rules. The ampersand can appear anywhere in the nested selector, including at the end for pseudo-classes such as &:hover or &.is-active.

It's worth noting that native nesting doesn't strictly introduce a new language; it's simply a more compact notation for selector combinations that flat CSS has always supported. The browser resolves the nesting internally into ordinary flat selectors while parsing, so specificity and cascade behavior fundamentally don't change, which means developers with basic CSS knowledge can pick it up immediately without learning a new syntax.

3. How Tailwind v4's Oxide engine processes native nesting

Tailwind v4 was rebuilt from the ground up on a new engine written in Rust, internally known as the Oxide engine, which uses Lightning CSS among other things for transforms such as vendor prefixing, minification, and CSS nesting. For projects that want to write native CSS features directly instead of exclusively combining utility classes in markup, this means nested CSS inside @layer blocks or in custom stylesheet files works without any additional Sass dependency.

The example below defines a card component with nested rules for an inner title and a hover state, combined with a utility base pulled in through @apply. The Oxide engine evaluates this structure at build time and produces optimized, flat CSS for delivery, while the source stays readable and logically grouped for developers.


.card {
  @apply rounded-lg border border-gray-200 p-4 shadow-sm transition-shadow;

  & .card-title {
    @apply text-lg font-semibold text-gray-900;
  }

  &:hover {
    @apply shadow-md;
  }

  &.is-featured {
    @apply border-blue-400 bg-blue-50;
  }
}

4. The difference from Sass nesting habits

Developers coming from Sass are used to implicit nesting, where a child selector combines with its parent automatically even without an ampersand, for example .card { p { margin: 0; } } with no leading character at all. Native CSS nesting, by contrast, often requires an explicit & as a separator, particularly when a pseudo-selector, a class, or an attribute selector follows directly, because the CSS specification is stricter here than the Sass preprocessor ever was.

Another difference concerns media queries and other at-rules: Sass has always allowed nesting @media blocks inside selector rules, and native CSS nesting now supports that too, though with a somewhat different internal resolution order that can, in rare edge cases, lead to slightly different specificity. Anyone porting existing Sass files one-to-one into native nesting should check each nested rule individually rather than assume identical behavior.

5. Using nesting well with @apply compositions

The most natural place for native nesting in a Tailwind project is recurring component classes assembled from multiple utility classes through @apply, for example buttons, badges, or card components that need to look identical wherever they're used. Instead of repeating a separate flat rule with a full selector for every state, every inner building block, and every pseudo-class, these variants nest directly inside the main rule, which makes the relationship visible right in the source.

This bundling is especially helpful when a component has several related sub-states, for instance hover, focus, and disabled states that all conceptually belong to the same class. Rather than maintaining three separate rules scattered across different parts of the file, nesting keeps a component's complete definition in one place, which makes maintenance and refactoring noticeably easier, particularly in larger projects with many reused component classes.

6. When nesting actually makes sense in a utility-first context

In a strictly utility-first project, the need for custom nested CSS stays fundamentally small, because most styling decisions happen directly in the markup through utility classes and never need a dedicated CSS rule. Nesting pays off where a component is reused many times across the project and the utility classes in the markup itself would already be unwieldy, or where third-party markup needs styling and offers no classes of its own for targeted utility application.

A typical warning sign of overusing nesting is when a nested CSS file starts to recreate the same structure as a full component library, with deeply nested selectors spanning many levels. At that point it's worth asking whether a real reusable component in Alpine.js or a PHTML template partial wouldn't be the cleaner solution, rather than using CSS selectors as a substitute for missing component structure.

7. Nested media queries and container queries

Native CSS nesting works not only with regular selectors but also with at-rules such as @media and @container, which can be nested directly inside a component rule. For Tailwind projects that define their own container query breakpoints in addition to the built-in responsive prefixes, that means a component's responsive logic can sit right next to its base definition instead of ending up in a separate media query block at the end of the file.

That spatial closeness between the base rule and its responsive adjustment noticeably improves readability, since a developer reading a component definition immediately sees which responsive variants exist, instead of scanning the file for scattered media query blocks. This closeness pays off especially with container queries, which modern Tailwind projects increasingly use instead of classic viewport media queries, since the container context and the component are tightly coupled anyway.

8. Browser compatibility of native CSS nesting

Native CSS nesting is supported by all current versions of the major browser engines, meaning Chrome and Edge on Blink, Firefox on Gecko, and Safari on WebKit, with support maturing steadily since each engine's rollout starting in 2023. For projects that still need to support older browser versions, the Tailwind v4 build engine automatically resolves nesting into flat CSS, producing a stylesheet compatible with older target environments without developers having to give up the more compact notation manually.

This automatic transformation means the decision to use native nesting in the source is independent of the actual target browser support, since the build process handles the translation. It's still worth setting a realistic browserslist configuration for the project, so the engine knows how aggressively it needs to transform and whether a more modern, compact output is possible or a more conservative, broadly compatible variant is required instead.

9. Best practices for nesting in Tailwind projects

A solid rule of thumb is to keep nesting to at most two or three levels deep, because deeper nested CSS reintroduces the same readability problems that utility-first was meant to avoid in the first place, namely hard-to-follow specificity chains. Instead of building a deep hierarchy with many levels, a flatter structure with clearly named component classes, each nested on its own without nesting into each other, is usually the better fit.

It's also worth deliberately reserving native nesting for cases where a component genuinely needs several related rules, rather than as a general replacement strategy for utility classes in markup, since doing so would erase Tailwind's core advantage of making styling decisions directly visible in the HTML. Nesting is a tool for the minority of cases where real CSS is required, not a substitute for the utility-first approach as a whole.

Aspect Sass nesting Native CSS nesting Tailwind v4
& selector Optional, implicit nesting possible Often required explicitly, especially before pseudo-classes Handled correctly through the Oxide engine
Nested media queries Yes, supported for a long time Yes, since the 2023 browser rollouts Possible right next to the component rule
Compilation Requires a build step with a Sass compiler No build step, runs natively in the browser Flattened automatically for older target browsers when needed
Dependencies node-sass or dart-sass as a dev dependency None, part of the CSS specification No additional dependency beyond Tailwind itself

Mironsoft

Tailwind CSS architecture, design systems, and performance

Tailwind frontends that stay maintainable despite thousands of utility classes?

We review existing Tailwind projects for bloated class lists, inconsistent design tokens, and unused CSS remnants, then build a design system that scales cleanly instead of getting messier with every component.

Design System Review

Checking tokens, spacing scale, and component consistency for maintainability.

Performance Optimization

Systematically reducing CSS bundle size, purge configuration, and load times.

Component Architecture

Building reusable, well-structured components instead of sprawling class lists.

10. Summary

Native CSS nesting in Tailwind v4 at a glance

& selector

Placeholder for the enclosing selector, often required explicitly before pseudo-classes.

Oxide engine

Tailwind v4's Rust engine processes native nesting and flattens it when needed.

Sass difference

No implicit nesting, an explicit & is needed before classes and pseudo-selectors.

Where to use it

Mainly worthwhile for @apply compositions and recurring component classes.

11. FAQ: Native CSS nesting in Tailwind v4 at a glance

1What is the difference between flat CSS and native CSS nesting?
Native nesting is a more compact notation for the same selector combinations flat CSS already supported, and the browser resolves the nesting internally into normal flat selectors without changing specificity or cascade behavior.
2Do I need to install a Sass compiler to use nesting in Tailwind v4?
No, Tailwind v4 processes native CSS nesting directly through its new Rust-based engine, so a separate Sass compiler is no longer needed for this purpose.
3Why doesn't .card { p { margin: 0 } } always work directly like in Sass?
Native CSS nesting often requires an explicit ampersand as a separator, particularly when a pseudo-class or attribute selector follows directly, whereas Sass allows implicit nesting.
4Can I nest media queries inside a component rule?
Yes, native CSS nesting supports nesting @media and @container rules directly inside a selector rule, keeping a component's responsive logic right next to its base definition.
5Does native nesting work in older browsers?
The Tailwind v4 build engine automatically flattens nested CSS into flat CSS when needed, so older target environments still receive a compatible stylesheet, provided the browserslist configuration is set accordingly.
6Should I replace utility classes in markup with nested CSS?
No, nesting suits the minority of cases where real CSS is required, such as @apply compositions or third-party markup, not as a general replacement strategy for the utility-first approach.
7How deep should CSS nesting go in a Tailwind project?
A solid rule of thumb is at most two to three levels, because deeper nested CSS reintroduces the same readability problems that utility-first is meant to avoid.
8What is the Oxide engine in Tailwind v4?
The Oxide engine is Tailwind v4's new build engine written in Rust, which uses Lightning CSS among other things for transforms such as vendor prefixing, minification, and CSS nesting.
9Does native nesting change specificity?
Fundamentally no, since the browser resolves the nesting internally into normal flat selectors, though in rare edge cases involving media queries the internal resolution order can differ slightly from Sass.
10Is native nesting a good fit for third-party widgets?
Yes, especially for markup you don't control yourself and that offers no classes of its own for targeted utility application, nested CSS with the & selector is often the most practical solution.