CSS Beautifier
Paste minified or messy CSS and format it into properly indented, readable code, or minify it back down.
About the CSS Beautifier
Beautify walks through the pasted CSS character by character, tracking brace depth so nested blocks like @media queries indent correctly and never mistaking a semicolon inside url(...) or a quoted string for the end of a declaration. Minify runs the same tokenizer in reverse, stripping comments and collapsing whitespace down to a single compact line. Comments that sit between rules are kept on their own line during beautifying instead of getting merged into whatever declaration follows them.
Why it's a real tokenizer, not a find-and-replace regex
A lot of "CSS beautifiers" are just a chain of regex substitutions that add newlines after {, }, and ;. That approach breaks the moment a semicolon or brace appears somewhere it shouldn't be treated as a delimiter, most commonly inside a url(...) value or a quoted string. This tool instead walks the input one character at a time and keeps three pieces of state: inStr (are we currently inside a quoted string, and which quote character opened it), parenDepth (are we inside parentheses, which covers url(), calc(), and similar functions), and level (how many { braces deep we currently are, which drives the indentation). The default seeded example in the textarea, background:url(x;y.png), exists specifically to demonstrate this: that semicolon sits inside the url() parentheses, so the parser's parenDepth check skips it entirely instead of treating it as the end of a declaration.
How string and escape handling works
When the tokenizer hits a quote character, it records which quote (" or ') opened the string and stays in string mode until it sees that same character again unescaped. Critically, it checks for a backslash first: if it finds \ while inside a string, it consumes that character and whatever follows it as a pair, so an escaped quote like \" inside a string value never prematurely ends the string. Without this check, a CSS value like content: "she said \"hi\"" would get mangled.
What happens to comments
Beautify treats a comment differently depending on where it appears. If the buffer of pending text is empty when a /* ... */ comment is encountered, the comment is standalone, it gets its own line at the current indentation level. If there's already pending text in the buffer (meaning the comment appears mid-declaration or mid-selector), it gets folded into that buffer instead of breaking onto its own line. Minify takes a simpler approach: comments are stripped out entirely with a single regex pass before any other processing, since there's no reason to ship comment bytes to production CSS.
The stash-and-restore trick behind Minify
Minifying is riskier than beautifying because whitespace inside a url() or a quoted string is meaningful and must survive. This tool's minifier first scans for every url(...) call and every quoted string, replaces each one with a short placeholder token built from an unprintable marker character (character code 1) plus an index number, then runs its aggressive whitespace-collapsing regexes across the now-placeholder-safe text, and finally swaps the placeholders back for the original untouched strings. It also removes the trailing semicolon right before a closing brace (color:red;} becomes color:red}), which is valid CSS and saves a byte per rule.
A known limitation: it isn't a spec-validating parser
This tool formats structure, brace nesting, selectors, and declarations, but it doesn't validate that a property name is real or that a value is syntactically correct CSS. Malformed input (an unclosed string, a stray brace) will still produce some output rather than throwing a parse error, because the tokenizer always flushes whatever's left in its buffer at the end rather than failing. If you need CSS syntax validation, pair this with your build tool's linter (stylelint) rather than relying on this formatter to catch errors.
Frequently Asked Questions
Will beautifying break a url() that contains a semicolon or special characters?
No. The parser tracks parenthesis depth separately from brace depth, so any character inside url(...), including semicolons, colons, or commas, is treated as part of the value and never mistaken for a CSS delimiter.
Does the minifier strip out my CSS comments?
Yes, Minify removes all /* ... */ comments before processing. If you need to preserve a license header or attribution comment, keep a separate copy of the original file, since minified output has no comments at all.
What happens to whitespace inside quoted strings when I minify?
It's preserved exactly. Before collapsing whitespace, the minifier temporarily replaces every quoted string and url() value with a placeholder token, runs its whitespace and punctuation cleanup, then restores the original strings unchanged, so a value like content: "a b" keeps its two spaces.
Does this tool validate whether my CSS is syntactically correct?
No. It reformats structure (indentation, spacing, brace placement) but doesn't check that property names or values are valid CSS. For linting and error detection, use a dedicated tool like stylelint alongside this formatter.
Will nested @media query blocks be indented correctly?
Yes. The tool increments its indentation level on every opening brace and decrements it on every closing brace, so a rule nested inside an @media block gets one extra level of indentation automatically, with no special-casing needed for at-rules.
Can I paste SCSS or LESS code into this beautifier?
Basic brace-based nesting will format reasonably since the tokenizer just tracks braces, strings, and parentheses generically. However, SCSS/LESS-specific syntax like variables (@var, $var), mixins, or nested selector combinators isn't specially understood, so output correctness for those constructs isn't guaranteed the way it is for plain CSS.