Format, beautify and organize CSS code instantly with customizable formatting and syntax validation. Everything runs locally in your browser.
CSS
PRETTY
CSS
0 chars
Loading editor…
Paste CSS or upload a .css file to format it.
Waiting for CSS
CSS
Everything happens locally in your browser. Your CSS is never uploaded.
What is CSS formatting?
CSS ignores whitespace. A stylesheet written as one 4,000-character line and the same stylesheet spread over two hundred lines are identical to the browser — it parses both into exactly the same rules and paints exactly the same pixels. Formatting is entirely for the reader. It takes a file whose structure is buried in a wall of text and puts that structure back on the screen: one selector per line, one declaration per line, nested rules indented inside the rules that hold them.
Nothing changed except whitespace. The second version matches the same elements, sets the same properties and renders identically — but you can see in one pass that there are two rules, that the second responds to two states, and you could point at the line you wanted to change.
Everything here runs in your browser. The stylesheets people paste into a formatter are usually unreleased work from a private repository, so nothing is uploaded, stored or logged.
Why format CSS?
Because unformatted CSS hides exactly the things that go wrong with it. Almost every CSS bug is a question of which rule won — a selector one level too specific, a declaration repeated further down the file, a breakpoint that never matches — and all of those are invisible in a single line and obvious once the structure is on separate lines.
Diffs shrink to the actual change. With one declaration per line, adding a property is a one-line diff, in a pull request or in a diff checker. On a single-line rule it is a change to the whole rule, and nobody reviewing it can see what moved.
Duplicate and dead rules surface. A property set twice in one block is easy to miss in a paragraph of text and hard to miss on its own line — and this tool reports it besides.
Compiled output becomes readable.CSS pulled out of a framework build, a browser’s inspector or a CDN arrives as one long line. Formatting is the first step to understanding it, and often the only practical way to find the rule you need to override.
Silent mistakes stop being silent. A misspelled property is discarded by the browser without a word. The validation running alongside the formatter is where that becomes visible.
Teams stop arguing about style. One agreed set of options, applied by a tool, ends the discussion about where the brace goes.
Reviews get faster. A reviewer can see which selectors exist and which properties they set without rebuilding the rule in their head first.
Supported CSS features
Modern CSS has grown a great deal, and most of what it added is structure — layers, containers, nesting, :has(). Structure is precisely what a formatter exists to show, so the newer the stylesheet, the more formatting it repays.
A variable declared once on :root and read with var() everywhere else. Their values are never rewritten here — a custom property can hold a fragment of a value that only makes sense once something else pastes it in, so the text after the colon is reproduced exactly.
Flexbox
One axis, laid out by a container that distributes space along it. The shorthand hides three properties in `flex: 1 1 auto`, which is precisely why a formatted stylesheet helps — you can see at a glance which rules set the shorthand and which set a longhand under it.
Grid
Two axes at once. `grid-template-areas` draws the layout as a picture in strings, and that picture only reads as one if the strings keep their spacing — so they are reproduced character for character rather than normalised.
Media queries
The breakpoints a layout changes at. Inside the parentheses a feature is written like a declaration, so `(min-width:640px)` gets the same space after its colon that a declaration would, and an unknown feature name is reported — a query that never matches fails completely silently.
Animations
`@keyframes` blocks whose selectors are percentages, plus `from` and `to`. Each stop gets a block of its own with its declarations indented inside it, which turns a single-line keyframe pulled out of a build back into something you can read down.
Container queries
`@container` asks about the size of an ancestor rather than the viewport, which is how a component becomes genuinely reusable. Formatted and validated exactly like `@media`, because structurally it is the same thing pointed somewhere else.
Nesting
Native CSS nesting, and the preprocessor kind that came before it. `&` is a token like any other, so `&:hover`, `&--ghost` and `& .title` survive untouched, and each level of nesting gets a level of indentation.
Cascade layers
`@layer` decides which rules win before specificity is consulted at all. Both forms are handled: the bodiless `@layer base, components;` that declares the order, and `@layer base { … }` that fills one in.
Formatting features
Indentation
Two spaces, four spaces or tabs, applied to declarations, nested rules and the contents of every at-rule. Indentation here means one thing and one thing only: this is inside that. A rule nested in a media query is indented inside it, and its closing brace returns to the column of the line that opened it.
Property alignment
Turn on align colons and the property names in a block are padded so their colons form a column, which suits people who read a rule by scanning down its values. Alignment is computed per unbroken run of declarations — a comment is a visual break, and alignment should not reach across one.
Sorting is alphabetical, stable, and applied only within an unbroken run of declarations. That boundary is what makes it safe to turn on: a comment, a nested rule or an at-rule anchors everything around it, so /* IE fallback */ stays above the thing it explains. Because the sort is stable, a property set twice keeps its order — display: -webkit-box followed by display: flex still works afterwards. It is off by default, because reordering declarations is a real change to a cascade and should be a choice.
Syntax highlighting
Selectors, pseudo-classes, property names, values, numbers, strings, variables, functions, at-rules, comments and !important each get their own treatment, in both panels and in both light and dark themes. Colour literals get a token of their own, and a # is painted as a colour in a value and as an id in a selector — the same character, read by position. To rewrite one of those literals in another notation, the colour converter moves between HEX, RGB, HSL and the rest.
Validation
Every issue comes with a line, a column, a caret pointing at the exact character and something to do about it. What it checks is deliberately bounded to what can be established from the text with certainty:
Unterminated strings, comments and url()s. The most destructive class of error, because everything after the opening mark is being read as something it is not.
Unbalanced braces and parentheses. Reported against the one that has no partner, not against the end of the file.
A declaration with no colon, and a missing semicolon that has swallowed the declaration after it.
Empty selector parts and trailing combinators. A browser drops the whole rule when any selector in a list fails to parse, not just the broken one.
Property names a browser would not recognise, with a did-you-mean when the name is one edit away from a real one — including a swap of neighbouring letters, which is how heigth happens.
Media types and features that do not exist, which is worth catching because a query with an unknown feature never matches and says nothing.
It is a linter, not a browser. It cannot tell you that a colour is wrong, that a layout will overflow, or that a selector matches nothing on your page — and it does not pretend to.
CSS best practices
Pick a naming convention and keep it
BEM, utility classes, or something of your own — it matters far less which you pick than that you pick one. What a convention buys is that a class name tells you where it belongs before you go looking: .card__title is part of .card, and .card--ghost is a variant of it. Name for what a thing is, not for what it currently looks like: .callout survives a redesign and .blue-box does not.
Put your decisions in custom properties
Colours, spacing, radii and durations are decisions, and a decision written in forty places is forty places to change. Declare them once on :root, read them with var(), and a redesign becomes an edit to one block. They are live at runtime too, which is what makes a theme switch a matter of swapping a handful of values rather than shipping a second stylesheet.
Resets first, then tokens, then elements, then components, then utilities, then the breakpoints that adjust them. That order is not decoration — CSS resolves ties by document order, so a file whose order is arbitrary is a file where every conflict is settled by accident. Cascade layers make the same intent explicit, and are worth reaching for in anything large.
Keep specificity low and flat
A single class is enough to select almost anything. Long descendant chains and id selectors win now and cost later, because the only way to beat them is something even more specific — which is the path that ends in !important on every other line. Prefer one class; reach for :is() and :where() when you need to group selectors without inheriting their specificity.
Write for the reader, and let the tooling do the rest
A stylesheet is written once and read for years. Leave a comment for the why — the browser bug behind an odd-looking rule — and let the formatting carry the what. Ship minified output for the bytes, keep formatted source in the repository for the people, and never hand-maintain the minified version.
CSS formatter vs CSS minifier
They are the same operation pointed in opposite directions. A formatter adds whitespace so a person can read the file; a minifier removes it so a browser can download the file faster. Neither changes what the CSS does, and you want both — at different moments.
Format what you edit. Source in your repository, CSS pasted from a colleague, anything you are about to review or debug. This is where whitespace earns its keep.
Minify what you ship. The file the browser downloads. On a large stylesheet the saving is real — comments and indentation are a meaningful share of the bytes, and they help nobody at runtime.
Never maintain the minified copy. Minification is a build step, not a state your source lives in. Editing a minified file is how a small change becomes an outage.
Format when you inherit minified CSS. Overriding a framework means reading its compiled output first, and that is exactly the direction this tool is best at.
Both directions are here: Format and Minify sit side by side in the toolbar, over the same stylesheet, and the statistics panel shows what each one costs in bytes.
Common use cases
Seven situations where a formatter is the shortest route from a file you cannot read to one you can.
Website development
The everyday case. CSS grows by accretion — a rule added here, a breakpoint patched there — and running it through a formatter with one agreed set of options is how a file that four people have touched stops looking like it.
UI components
A component's styles are read far more often than they are written, usually by somebody trying to work out which rule is winning. One declaration per line and one selector per line is what makes that readable.
Framework customisation
Overriding a framework means reading its compiled output first. That output arrives minified, on one line, and formatting it is the only practical way to find the rule you need to beat.
Email templates
Email CSS is a different language with the same syntax: inline styles, table layouts, and a `<style>` block that half the clients ignore. Formatting it is how you audit what is actually in there before sending to a hundred thousand inboxes.
Design systems
A token file is a long list of custom properties, and the colour panel turns it into something you can check at a glance — including the moment it tells you the six greys you designed have become eleven.
Debugging
CSS copied out of a browser's inspector arrives as a wall of text with the shorthand expanded and the order changed. Formatting it, with the validation running alongside, is the first step in working out what happened.
Learning CSS
Structure teaches. Seeing every rule laid out the same way — selector, brace, one declaration per line — makes the shape of the language obvious far faster than reading prose about it.
Frequently asked questions
Is this CSS formatter free?
Yes. Formatting, minifying, validating, uploading, downloading and every option are free, with no account, no sign-up and no cap on how many stylesheets you format.
Is my CSS uploaded anywhere?
No. The stylesheet is tokenised, parsed and formatted by JavaScript running in your browser. Nothing is sent to a server, nothing is stored and nothing is logged. You can disconnect from the network after the page loads and the tool keeps working — which matters, because the CSS people paste into formatters is often unreleased work from a private repository.
Will formatting change how my page looks?
No. Formatting only changes whitespace and, if you ask it to, the quote a string is written with. Selectors, property names, values, comments and at-rules are reproduced token for token, so the formatted stylesheet matches the same elements and sets the same properties. The two options that can do more are turning comments off, which drops them, and sorting properties, which reorders declarations — both are off or safe by default, and both are described below.
Does it support SCSS?
Yes. Nested rules, `$variables`, `@mixin` and `@include`, `@use` and `@forward`, `@each` and `@if`, `%placeholders`, `#{…}` interpolation and `!default` are all understood, and `//` is treated as a comment rather than a syntax error. SCSS is detected automatically from any of those markers.
Does it support Sass, the indented syntax?
Yes. The indented syntax carries its structure in indentation rather than in braces, so it is bridged to the braced form, formatted with every option you have chosen, and written back out indented — the output is still Sass. Positions survive the round trip, so an issue reported at line 40 is at line 40 of what you actually wrote. Minified output is always braced, because minifying a syntax whose meaning lives in whitespace is a contradiction.
Does it support Less?
Yes. `@variable` definitions, parametric mixins, mixin calls such as `.bordered(2px);`, guards written with `when`, `@{…}` interpolation and escaped `~"…"` values are all handled. A mixin call is a statement rather than a broken declaration, so it is not reported as one.
How does flavour detection work?
Markers are scored rather than trusted one at a time, because every valid CSS file is also a valid SCSS file and a valid Less file — only the extensions are distinctive. `@mixin`, `#{…}` and `$var:` point to SCSS; `@name: value`, `when (…)` and `~"…"` point to Less; no braces and no semicolons at all means the indented syntax. A stylesheet with nothing distinctive in it stays CSS rather than being guessed at, because guessing wrong changes what `//` means.
Can I format CSS variables?
Yes, and their values are never rewritten. A custom property can hold anything at all — a whole shorthand, a fragment of a value, a token that only makes sense once `var()` pastes it somewhere else — so the text after the colon is reproduced exactly as written, with only the run of whitespace between tokens normalised.
Can I format Flexbox and Grid?
Yes. `grid-template-areas` strings keep their spacing so the ASCII picture of the layout still lines up, `aspect-ratio: 16 / 9` keeps its slashes, and `repeat(auto-fill, minmax(200px, 1fr))` gets a space after each comma and nowhere else. Nothing about a grid or a flex container is treated as a special case, because nothing about them needs one.
What does the validator check?
The things that can be established with certainty from the text: unterminated strings, comments and `url()`s; unbalanced braces and parentheses; a declaration with no colon; a property with an empty value; a missing semicolon that has swallowed the declaration after it; an empty part in a selector list; a selector ending in a combinator; a property name that is not one a browser knows, with a did-you-mean when it is one edit away; a declaration outside any rule; an unknown at-rule; a media type or feature that does not exist; and a property set twice to the same value. It is a linter, not a browser — it cannot tell you a colour is wrong or a layout will break.
Why does it warn about an unknown property?
Because a property a browser does not recognise is discarded without a word — no error, no fallback, nothing in the console. A typo in a property name is therefore completely silent, which is what makes it worth catching here. Vendor-prefixed names, custom properties, preprocessor variables and interpolated names are never questioned, since there is no list that could be complete.
Does sorting properties alphabetically break anything?
It is off by default, and when on it only ever moves a declaration within an unbroken run of its neighbours — a comment, a nested rule or a media query anchors everything around it. The sort is stable, so a property set twice keeps its order and a fallback such as `display: -webkit-box` followed by `display: flex` keeps working. It is still a real change to the cascade in principle, which is why it is a choice rather than a default.
What does align colons do?
It pads the property names in a block so their colons form a column, which suits people who read a rule by scanning down its values. Alignment is computed per unbroken run of declarations, for the same reason sorting works that way: a comment is a visual break, and alignment should not reach across one.
Can I minify CSS afterwards?
Yes — the Minify button, or Ctrl/Cmd+Shift+M. It collapses whitespace to the minimum that still parses, removes comments while keeping `/*!` licence headers, drops the last semicolon in each block, shortens `#ffffff` to `#fff` and `0.5em` to `.5em`, removes the unit from a zero length outside `calc()`, and folds adjacent rules that share a selector list or a body. Every one of those is a change to the text and not to what it renders.
Why does minifying keep the spaces in calc()?
Because they are required. `calc(100% - 10px)` is valid and `calc(100%-10px)` is not — the minus sign needs whitespace on both sides or it is read as part of the number beside it. The minifier tracks which function it is inside for exactly this reason, and leaves the arguments of `calc()`, `min()`, `max()` and `clamp()` alone.
Are comments preserved?
Yes, by default. A comment written at the end of a line stays at the end of that line, a comment on its own line keeps a line of its own, and a banner comment's continuation lines are re-indented so the asterisks stay in their column. A comment directly above a rule is treated as that rule's heading and never has a blank line pushed between them. Turn comments off and they are dropped entirely — except `/*!` headers, which are how licences are marked.
What does the colour panel show?
Every colour the stylesheet uses, grouped by what it renders as rather than by how it was written — so `#fff`, `#FFFFFF`, `white` and `rgb(255 255 255)` are one entry with a count of four. Each one is shown as a swatch with its hex, rgb and hsl notations, all copyable, and a click on the swatch jumps to its first use. Colours are read from declaration values only, so a `#header` selector is never mistaken for one.
Can I upload a stylesheet?
Yes. Use the upload button or drag a .css, .scss, .sass or .less file anywhere onto the tool. The file name is shown above the input panel and is reused when you download the result. Files are read as UTF-8, so accented and non-Latin text in comments and `content` strings survives intact.
How large a stylesheet can it handle?
Up to about 10 MB of text, which covers any framework build you are likely to meet. Formatting is debounced so typing stays responsive, and anything past 150 KB is moved onto a Web Worker so the page never stops responding while it runs. The editor only highlights what is on screen, which is what keeps scrolling through a multi-megabyte file smooth.
Can I search inside a large stylesheet?
Yes. The search button, or Ctrl/Cmd+F, opens a search over the input with every match highlighted, a match counter, and previous and next buttons to step through them. It searches whatever is in the panel — selectors, class names, ids, property names, values or variables. Escape closes it.
Are there keyboard shortcuts?
Ctrl/Cmd+Enter formats, Ctrl/Cmd+Shift+M minifies, Ctrl/Cmd+Shift+C copies the output, Ctrl/Cmd+Shift+D downloads it, Ctrl/Cmd+Shift+L loads another sample, Ctrl/Cmd+Shift+Delete clears the input, and Ctrl/Cmd+F opens the search. Escape closes the search.
Does it work offline?
Once the page has loaded, yes. Everything runs locally, so you can disconnect and keep formatting. A connection is only needed to load the page the first time.
Keep going
Tools that pair with this one
Same engine, same privacy model — everything below runs in your browser too.