Skip to main content

CSS Formatter / Minifier

Format, beautify and minify CSS code.

Reviewed by · Last reviewed

How to Use the CSS Formatter

  1. Paste your stylesheet into the input textarea. Raw unminified CSS, a single-line production bundle, or a fragment copied out of DevTools all work.
  2. Pick an indent style from the dropdown: 2 spaces (the common Prettier default), 4 spaces (Google's CSS style guide), or a tab character.
  3. Click Format to expand the source into one declaration per line with braces on their own lines, or Minify to collapse the rules into a single-line bundle suitable for shipping.
  4. Copy the result using the button above the output pane. You can also chain operations: format to inspect, then minify the same buffer before pasting into a build artifact.

What the Tool Does and How It Works

The formatter walks your source character by character using a lightweight tokenizer that tracks three states: inside a selector, inside a declaration block, and inside a string or url() literal. When it hits an opening brace it increases an indent counter, emits a line break, and buffers declarations until the matching close brace. Semicolons trigger newlines between declarations, and at-rules like @media, @supports, and @keyframes are recognised so their nested blocks receive an additional level of indentation.

Minification runs the opposite pass: whitespace collapses to single spaces, spaces around {, }, :, ;, and , disappear, and trailing semicolons inside the last declaration of each block are removed. Comments delimited by /* ... */ are stripped entirely. Because the tokenizer does not build a full AST, it preserves unknown properties and vendor prefixes verbatim rather than rejecting them, which means experimental CSS and future syntax still round-trip cleanly.

When You Would Reach for This

  • Inspecting a minified stylesheet shipped by a production site without opening a full IDE.
  • Preparing a CSS snippet for a blog post, Stack Overflow answer, or code review where readable diffs matter.
  • Shrinking a handwritten stylesheet before inlining it into a transactional email template that has no build step.
  • Switching an existing codebase between two- and four-space indentation when you adopt a new lint config.
  • Sanity checking that a copy-pasted third-party widget's styles contain no surprise imports or unclosed braces.
  • Normalising the output of several generators (Sass, PostCSS, Tailwind JIT) so diffs in git are about content, not whitespace.

Common Pitfalls

  • Unclosed blocks. A missing } causes every subsequent selector to appear nested. The tool will still emit output, but the indent counter drifts; look for selectors with impossibly deep indentation and fix the source.
  • Data URIs. Long base64 payloads inside url(data:image/png;base64,...) are preserved untouched. The minifier leaves them alone because line breaks would corrupt the decoded bytes.
  • CSS custom properties with semicolons. A value like --content: "a;b"; is handled correctly because the tokenizer tracks string state, but only if you used matched quotes.
  • Calc with spaces. Operators in calc(100% - 16px) require surrounding whitespace per CSS Values Level 4; the minifier preserves the single spaces there.
  • Nested CSS. Native nesting (Chrome 112+) using & parses correctly but is treated as plain blocks, so you may want to keep the indentation your browser's DevTools produced.

CSS Syntax Background

The formal grammar lives in the W3C's CSS Syntax Module Level 3. That spec defines CSS as a stream of tokens: whitespace, comments, identifiers, functions, at-keywords, and blocks delimited by {, [, and (. Any whitespace between tokens is semantically irrelevant except inside strings and calc() operators, which is exactly why both "pretty" and "minified" representations describe the same stylesheet. Browsers are required to implement error recovery - an unknown property is skipped to the next semicolon and a malformed block is skipped to the next matching brace - which is why bad CSS still "works" on some rules. The formatter mirrors that behaviour instead of halting on the first unfamiliar token.

How It Compares to Other Tools

Against Prettier or stylelint --fix, this tool is intentionally smaller. Prettier builds a full PostCSS AST and reformats according to a style that handles long selectors, property sorting, and quote normalisation that a regex-based pass cannot. If you work inside a repo, prefer npx prettier --write or your editor's format-on-save. Where this tool wins is the zero-install case: one-off snippets from a DevTools panel, inline email CSS, or a quick minification for a CMS field that otherwise has no build pipeline. For heavy minification (dead rule removal, shorthand merging) reach for cssnano or lightningcss; this tool is a compressor, not an optimizer.

Frequently Asked Questions

Does this formatter parse a real CSS AST?

No. It uses a tokenizer that tracks braces, semicolons, and string delimiters, not a full syntax tree. That keeps the bundle tiny and makes the tool tolerant of experimental or vendor-specific properties it has never seen. The trade-off is that it will not refactor shorthand properties, remove unreachable rules, or alphabetise declarations the way a dedicated tool like Prettier or cssnano would.

Is any part of my CSS uploaded while I use the page?

No. The page ships a Preact island that runs the formatter in your tab; there is no fetch call to a backend endpoint during processing, and no service worker intercepts the input. You can disable the network tab in DevTools after the initial page load and every button still works. The result buffer lives in JavaScript memory and is discarded when you close the tab.

Why does the minified output still contain some spaces?

CSS requires whitespace in a few specific places: between the plus or minus operators inside <code>calc()</code>, after an <code>@import</code> URL when followed by media queries, and inside string literals. Removing those would produce invalid CSS, so the minifier keeps them. Every other run of whitespace collapses to nothing or a single space where needed for tokenisation.

Does it handle Sass, Less, or PostCSS syntax?

Only to the extent that they look like CSS. Variables using <code>$</code>, <code>@</code>, or <code>--</code> survive round-trips, but Sass-specific constructs like <code>@mixin</code>, <code>@include</code>, or parent selectors with <code>&amp;</code> are treated as opaque blocks. Run your source through the Sass or Less compiler first if you need true pretty-printing of preprocessor output.

How are CSS comments handled by each mode?

Format preserves <code>/* ... */</code> comments and places block-level comments on their own line. Minify strips all comments, including license banners. If you need to preserve a license header after minification, add a <code>/*!</code> bang-comment and post-process the output - this tool does not currently special-case bang comments.

What is the largest stylesheet I can paste in?

There is no hard cap. In practice anything under one megabyte formats in well under a second on a modern laptop. Stylesheets past five megabytes can make the tab briefly unresponsive because the tokenizer is synchronous. For build-time processing at that scale, pipe through <code>lightningcss</code> or <code>esbuild</code> on the command line instead of doing it in a browser tab.

Can I use the minified output directly in a <code>&lt;style&gt;</code> tag?

Yes. The minifier produces valid CSS that any browser will parse. A common pattern is to minify a component stylesheet here and then inline it into the <code>&lt;head&gt;</code> of an HTML email template or a landing page that has no build step. Remember to escape <code>&lt;/style&gt;</code> sequences if they appear inside a string.

Does it change the cascade order of my rules?

No. The tokenizer emits rules in the exact order it read them. CSS specificity and source order are preserved, so two stylesheets that differ only in whitespace produce identical computed styles in the browser. That property is what makes the format and minify operations safe refactors rather than rewrites.

How should I handle stylesheets with <code>@import</code> at the top?

At-import rules are recognised and kept at the top of the output, because CSS requires them to appear before any other rules except <code>@charset</code>. The formatter does not follow the imports or inline them - for that, use a bundler like <code>postcss-import</code>. Running this tool on the main file alone will still produce a valid stylesheet.

Why would I format before committing CSS to git?

Consistent whitespace makes diffs reviewable. A single-line minified file forces reviewers to squint at a huge changed-line count when only one selector actually changed. Pretty-printing the source before commit means diffs show just the altered declarations, which is why most teams configure a pre-commit hook that runs Prettier or stylelint on staged stylesheets.

More Developer Tools