CSS to SCSS Converter
Convert plain CSS to nested SCSS (Sass) instantly. Automatic nesting, variable extraction, and parent selector optimization in your browser.
About
Manually refactoring flat CSS into nested SCSS is error-prone. A misplaced brace or a wrong & reference breaks the entire compiled output, and debugging generated CSS back to its SCSS source wastes hours. This converter parses your CSS into an abstract syntax tree, identifies selector relationships via longest common prefix matching, and reconstructs the rules as properly nested SCSS with parent selectors (&). It handles pseudo-classes, pseudo-elements, BEM patterns, combinators, media queries, and @keyframes. The tool approximates optimal nesting depth assuming standard specificity practices. Note: it does not infer @mixin or @extend usage since those require design-intent knowledge the source CSS cannot provide.
Formulas
The converter operates on a deterministic parsing pipeline rather than mathematical formulas. The core logic follows three stages:
Selector nesting uses a Longest Common Prefix algorithm. Given two selectors S1 and S2, the shared prefix P is extracted at the compound-selector boundary level:
where parts splits a selector by descendant combinators (spaces) into an ordered list. The remainder after removing P becomes a nested child rule. BEM suffixes (__ and --) trigger the parent reference operator & concatenation instead of descendant nesting. Pseudo-selectors (: and ::) are detected via regex pattern /^[:&\[]/ and always use & joining.
Reference Data
| CSS Feature | SCSS Equivalent | Example Input | Example Output |
|---|---|---|---|
| Descendant selector | Nesting | .nav .link { } | .nav { .link { } } |
| Child combinator | Nested with > | .nav > .link { } | .nav { > .link { } } |
| Pseudo-class | Parent selector & | .btn:hover { } | .btn { &:hover { } } |
| Pseudo-element | Parent selector & | .btn::before { } | .btn { &::before { } } |
| BEM element | Parent selector & | .card__title { } | .card { &__title { } } |
| BEM modifier | Parent selector & | .card--dark { } | .card { &--dark { } } |
| Adjacent sibling | Nested with + | .a + .b { } | .a { + .b { } } |
| General sibling | Nested with ~ | .a ~ .b { } | .a { ~ .b { } } |
| Media query | Nested @media | @media (max-width: 768px) { .nav { } } | .nav { @media (max-width: 768px) { } } |
| Keyframes | Preserved at root | @keyframes fade { 0% { } } | @keyframes fade { 0% { } } |
| Multiple selectors | Split & nested individually | .a .b, .a .c { } | .a { .b, .c { } } |
| Attribute selector | Parent selector & | .input[type="text"] { } | .input { &[type="text"] { } } |
| Root-level properties | Preserved at root | :root { --color: red; } | :root { --color: red; } |
| Comments | Preserved in place | /* header */ .h { } | /* header */ .h { } |
| @import | Preserved at root | @import url('a.css'); | @import url('a.css'); |
| @font-face | Preserved at root | @font-face { font-family: X; } | @font-face { font-family: X; } |
| Nesting depth limit | Max 4 levels recommended | Deep selectors | Flattened beyond limit |