By Tim King · Updated
CSS Nesting Converter
Nest Flat CSS or Flatten Nested CSS
OneTask is free, with no sign-up, and built by one person.
If this tool saved you time, a coffee helps keep new ones coming.
How the CSS Nesting Converter works
This CSS nesting converter works in both directions. Paste nested CSS to flatten it into plain rules
any browser or tool can read, or paste ordinary flat CSS to group related rules under their parent
selector with native & nesting.
Native CSS nesting lets you write child rules inside a parent rule, the way Sass and Less have
allowed for years, but without a build step. Instead of repeating .card on five lines you write it
once and nest h3, &:hover and a media query inside it. Every current browser supports it:
Chrome and Edge 120, Safari 17.2 and Firefox 117 handle the relaxed syntax used here.
Converting matters in both directions. Flattening is useful when a linter, an email template, an older browser or a CSS tool you rely on does not understand nesting yet. Nesting is useful when you are tidying an old stylesheet and want related rules kept together.
How to use the CSS nesting converter
- Choose a direction: flatten nested CSS, or nest flat CSS.
- Paste your stylesheet into the box.
- Copy the result. Comments are removed during conversion, so keep your original if they matter.
How flattening works
| Nested input | Flat output | Rule applied |
|---|---|---|
.card { h3 { } } |
.card h3 |
No & means a descendant |
.card { &:hover { } } |
.card:hover |
& is replaced by the parent |
.card { > p { } } |
.card > p |
A leading combinator joins to the parent |
.card { .dark & { } } |
.dark .card |
& can appear anywhere |
.a, .b { span { } } |
.a span, .b span |
Every parent pairs with every child |
.card { @media (...) { } } |
@media (...) { .card { } } |
At-rules are lifted out |
When the parent is a complex selector and & is not at the start, the parent is wrapped in :is().
That matches how browsers read native nesting, and it avoids changing which elements match.
@keyframes, @font-face and similar blocks are copied through unchanged.
How nesting works
The tool looks at each rule's leading class, ID or element. Rules next to each other that start with
the same one are grouped. .card, .card h3 and .card:hover become one .card block holding
its own declarations, then & h3 and &:hover. Rules inside a @media block are grouped the same
way within that block.
Only neighbouring rules are merged, on purpose. Moving a rule earlier or later in a stylesheet can change which declaration wins when two rules have the same specificity. Grouping only adjacent rules keeps the cascade order you already had.
Tips and pitfalls
& versus no &. In native CSS, h3 inside .card means a descendant, the same as & h3.
But :hover written without & means .card :hover, any hovered descendant. Always write
&:hover and &.active when you mean the element itself. The nested output always includes &,
which also works in the few browsers that only support the stricter early syntax.
No string concatenation. Sass lets you write &__title to build .card__title. Native CSS
nesting does not, because & stands for a whole selector, not text. The flatten mode substitutes
the parent as text, so Sass input with &__title still comes out as .card__title, but the nested
original would not work in a browser.
Specificity can rise. The :is() wrapper takes the specificity of its most specific argument.
A rule nested under #main, .content behaves as if it had an ID in every branch. Flattening shows
you exactly what that looks like.
Do not nest too deep. Three levels are usually the limit before a stylesheet gets hard to read and selectors become longer than they need to be. Flatten, then nest again, to see the real selectors you were writing.
Declarations after nested rules. Older browsers moved any declaration that came after a nested rule up to the top of its block. Keep declarations first, then nested rules, which is also the order the nest mode produces.
Reading the result
In flat output, each rule appears in source order with selectors from a list on separate lines, and
consecutive rules under the same media query share one @media block. In nested output, a block's
own declarations come first, followed by a blank line and each nested rule. Rules that could not be
grouped, such as one starting with an attribute selector, are copied through flat.
FAQ
Is native CSS nesting the same as Sass nesting?
Mostly, but not entirely. Both use & for the parent and allow nested media queries. Native CSS
cannot join text onto &, such as &__title, and it wraps complex parents in :is(), which can
change specificity compared with Sass.
Can I use native CSS nesting in production?
Yes for most sites. It works in Chrome, Edge, Safari and Firefox released since late 2023. If you must support older browsers, flatten the CSS with this tool or a build step before shipping.
Does flattening change how my styles behave?
No. The flat rules match the same elements in the same order. Where & sits inside a complex
parent, the tool keeps the browser's meaning by wrapping the parent in :is() rather than gluing
selectors together.
Why were my comments removed?
Comments are stripped before parsing so that braces or semicolons inside them cannot confuse the converter. Keep a copy of your original stylesheet if the comments carry notes you need.
See also: all Data & Code tools, Units, Images, Audio & Video, Documents.
Related tools
:has() Selector Builder
Pick a :has() pattern, see it work live and copy the HTML and CSS.
Cascade Layers Generator
Set your @layer order and get the blocks or imports to paste.
Tailwind To CSS
Turn Tailwind utility classes into plain CSS declarations.
CSS Generator
Build a formatted CSS rule from a selector and a form of properties.
Media Query Generator
Compose any @media query from feature options and test it live.