CSS Minifier
Minify CSS safely, preserving strings, custom properties and licence comments.
CSS Minifier tool
What this tool does
Paste a stylesheet and it comes back with comments gone, whitespace collapsed, the final semicolon of each block removed and numbers trimmed to their shortest legal form — along with the before and after byte counts and the percentage saved. A typical hand-written stylesheet loses between 15% and 30%.
Unlike the regular-expression minifiers that dominate search results, this one reads the stylesheet as tokens, so it knows a semicolon that ends a declaration from one sitting inside a string or a data URI.
Common uses
- Shrinking a stylesheet for a project that has no build step — a landing page, an email template, a WordPress theme.
- Compacting the critical CSS you are about to inline into
<head>, where every byte is on the critical rendering path. - Producing a single-line value to embed in a JavaScript string or a CMS field.
A short example
This input:
.card {
margin : 0.5rem 0 ; /* top and bottom */
width : calc( 100% - 2rem ) ;
} becomes:
.card{margin:.5rem 0;width:calc(100% - 2rem)}
Note what survived: the space between .5rem and 0, because they are
two separate values, and the spaces around the minus inside calc(), because
removing them makes the expression invalid.
What a regex minifier gets wrong
Four constructs break naive minification, and all four appear in ordinary stylesheets. A
string can contain anything: content: "a; b {c}" has a semicolon and a
pair of braces that are data, not structure. An unquoted url() can contain a
semicolon and a colon — every base64 data URI does. A custom property's value is not CSS at
all but an arbitrary token stream, so it must be copied out verbatim rather than reformatted.
And a comment opener inside a string, content: "/*", will make a
comment-stripping regex eat the rest of the file.
The tokenizer handles each of those as one indivisible unit, then decides about whitespace a
token pair at a time, tracking selector and declaration contexts separately. That matters: in
a selector div :hover and div:hover select different elements, so
the space before a colon is load-bearing; in a declaration it never is. Likewise
@media screen and (min-width:40em) must keep the space before its bracket, or
and ( fuses into a function token and the breakpoint stops working.
Worth knowing
Minification is a fraction of the win that compression is. A stylesheet that drops 20% here will usually drop 80% under gzip, because repeated property names compress beautifully. The two stack, but if you can only do one, enable compression on the server. This tool also stops short of what a full optimiser such as lightningcss does: it does not merge duplicate selectors, reorder declarations or drop rules for browsers you no longer support. Those change the cascade in ways that need a test suite behind them, and this page has none of your tests.
Frequently asked questions
Why can’t a minifier drop the unit from every zero?
Because only lengths may lose it. CSS allows 0px to shrink to 0, but a time, angle, frequency or resolution value requires its unit, so transition-duration: 0s is valid where a bare 0 is not. Inside calc() the rule tightens again: a unitless zero is a plain number rather than a length, which makes calc(100% - 0) invalid while calc(100% - 0px) parses.
Why did my @import stop working after I inlined the minified CSS?
Position, not minification. An @import is honoured only when it precedes every rule except @charset and @layer, so pasting a stylesheet below existing declarations in a style element makes the browser drop the import — silently, with nothing in the console. Move imports to the top of the combined file, or resolve them at build time; each one costs an extra round trip on the critical path regardless.
Why is my stylesheet still huge after minifying?
Minification removes characters, never rules. A framework build ships every selector it defines whether a page uses eight of them or eight hundred, and that dead weight is usually most of the file. Chrome DevTools’ Coverage panel reports the unused share against a real page load, and content-aware tooling such as Tailwind’s build step or PurgeCSS is what actually deletes those rules — a far larger win than whitespace.