CSS Minifier - Minify CSS Online Without Breaking calc(), url() or Strings
Paste CSS and get a smaller copy with the comments and extra white space gone, plus the size before and after and a gzip estimate.
Maintained by Hirantha Sandaruwan Lakshan. Updated 13 October 2026.
About this tool
It reads your CSS the way a browser does, so a string, a url(), a calc() expression or a media query is never mangled, and it checks its own result against your input. Switch to Beautify to turn minified CSS back into indented, readable rules. Nothing is uploaded.
How it works
A minifier that works by search and replace on the whole text breaks CSS sooner or later, because the same characters mean different things in different places: a space inside a string is content, a space inside calc() is syntax, and a space before a colon in a selector changes what it matches. This tool first splits your CSS into tokens following the CSS Syntax Module Level 3 rules: comments, strings with their escapes, url() values, identifiers, numbers with units, colours, brackets and punctuation. Only then does it decide, token pair by token pair, whether a space between them can go.
A space is removed only next to { } ; and commas, just inside ( ) and [ ], around / and * inside values, around the combinators > + ~ in selectors, and around the colon in a declaration or a media feature. Everything else keeps a single space. That is why calc(1px + 2px) keeps the spaces around + and - (CSS Values 4 says whitespace is required on both sides of those two operators, while * and / need none), why "and (min-width: 48em)" keeps the space after and (Media Queries 4 says it is required, otherwise "and(" reads as a function), and why "a :hover" stays different from "a:hover". The last semicolon before a closing brace is dropped, and @charset stays first in the file, with the single space before the quoted name that browsers require.
With "Shorten values" on, numbers are written in their shortest form (0.5 becomes .5, 1.50 becomes 1.5), a zero length loses its unit (0px becomes 0, which CSS Values 4 allows for lengths), and a colour such as #ffffff becomes #fff when every pair of digits repeats. Percentages, times and angles keep their units, so 0%, 0s and 0deg are untouched. A unit is never removed inside calc(), min(), max(), clamp(), var() or env(), where a bare 0 would be invalid or change the result, nor in the flex shorthand or inside @property. Old Internet Explorer filters (progid:) and expression() values are not rewritten at all. The value of a custom property (--name) is kept as written apart from comments and the space at its start and end, because the page may use it in ways no tool can see.
After minifying, the tool tokenizes its own output and compares it with your input, ignoring white space, comments and the final semicolon in each block, and tells you whether the two match. The gzip figure is an estimate made with your browser's CompressionStream; a web server may use another compression level, so treat it as a guide. Beautify uses the same tokenizer, so it also keeps strings and url() intact, puts each selector of a list on its own line, and keeps any comments it finds. Problems it cannot repair for you, such as a brace that is never closed or a stray semicolon between rules (a browser reads that semicolon as the start of the next rule and ignores the rule), are reported above the result.
Worked examples
Spaces, a colour and a zero
A four-line rule ("a {", then "color : #ffffff ;" and "margin : 0px 0.5em ;" each indented by two spaces, then "}") is 48 bytes. It becomes "a{color:#fff;margin:0 .5em}", which is 27 bytes, a saving of 43.8%. The spaces around the colon and the braces are gone, #ffffff is #fff, 0px is 0 and 0.5em is .5em.
calc() and a media query keep the spaces they need
".box { width: calc( 100% - 2 * 1.5rem ); }" and "@media screen and ( min-width : 48em ) { .box { margin : 0 auto } }" become ".box{width:calc(100% - 2*1.5rem)}@media screen and (min-width:48em){.box{margin:0 auto}}". The spaces around the minus sign and after "and" stay, the spaces around the * go.
A descendant selector is not a pseudo-class
".nav a :hover" selects any element in a hovered state inside a link in .nav, while ".nav a:hover" selects the link itself. A careless minifier turns the first into the second. Here the space before the colon is kept, so both rules come out exactly as meaningful as they went in.
A licence comment survives
With "Keep the first /*! comment" selected, "/*! Theme v1 | MIT */ /* layout */ .card{ padding: 0.75rem 1.25rem; }" keeps the first comment and drops the second: the result starts with "/*! Theme v1 | MIT */". If an @charset rule comes after that comment, it is moved in front of it, because @charset has to be the first thing in the file, and the tool says so when it does.
What the minifier changes and what it leaves alone
| Input | Output | Why |
|---|---|---|
| a { color : red ; } | a{color:red} | Spaces around braces, colons and semicolons go, and so does the last semicolon. |
| a{margin:0px 0.50em} | a{margin:0 .5em} | A zero length needs no unit, and a number can lose its leading and trailing zeros. |
| a{color:#FFFFFF} | a{color:#fff} | Each pair of hex digits repeats, so the short form is the same colour. |
| a{width:calc(1px + 2px)} | a{width:calc(1px + 2px)} | + and - need a space on both sides inside calc(). |
| a{width:calc(2 * 3px)} | a{width:calc(2*3px)} | * and / do not need spaces. |
| @media screen and (min-width: 600px){a{top:0}} | @media screen and (min-width:600px){a{top:0}} | The space after and stays; the space after the colon goes. |
| a :hover{top:0} | a :hover{top:0} | The space is a descendant combinator, so it is kept. |
| a > b + c{top:0} | a>b+c{top:0} | Spaces around the combinators > + ~ are not needed. |
| a{content:"a b\201C"} | a{content:"a b\201C"} | A string, with its double space and its escape, is copied as written. |
| a{background:url( x.png )} | a{background:url(x.png)} | Space inside the parentheses of an unquoted url() is not part of the address. |
| a{--x:0px 1px;--y:#ffffff} | a{--x:0px 1px;--y:#ffffff} | A custom property value is kept exactly as written. |
| a{transition:0s;margin:0%} | a{transition:0s;margin:0%} | Times and percentages keep their unit. |
| a{color:red ! important} | a{color:red!important} | Space around the exclamation mark is not needed. |
Frequently asked questions
Is it safe to minify CSS?
It is safe when the minifier only removes what the browser ignores, and that is the aim here. The tool reads the CSS as tokens, keeps a single space wherever two tokens would otherwise run together, and then checks its own output against your input and reports a mismatch. Keep your original file, and test the page after you deploy the minified copy, as you would after any build step.
Why does calc(1px + 2px) keep its spaces?
Because CSS requires them. In a calc() expression whitespace is required on both sides of + and -, so calc(1px+2px) is invalid and the browser throws the whole declaration away. The spaces around * and / are optional and are removed.
Does it change my CSS custom properties?
No. The value of a custom property such as --gap: 0.50rem is kept as you wrote it, apart from comments and the space at the start and end. A custom property can be used inside calc(), in a string or in JavaScript, so shortening it could change the result in a place the tool cannot see.
Will turning 0px into 0 break anything?
Not for lengths. CSS lets a zero length be written without a unit. The tool does not do it for percentages, times or angles (0%, 0s and 0deg stay), inside calc(), min(), max(), clamp() and var(), or in the flex shorthand, where a bare 0 can mean something else. You can switch the shortening off completely.
Does it keep licence comments?
Yes. A comment that starts with /*! is the usual way to mark a licence or copyright notice that should survive minification. By default the first one is kept; you can also keep all of them, or remove every comment. Many open source licences require the notice to stay with the code.
How much smaller will my CSS get, and what about gzip?
It depends on how the file is written. A stylesheet with generous indentation and many comments shrinks a lot; one that is already compact, or that is mostly custom property values (which are kept as written), saves little. Servers usually also compress CSS with gzip or Brotli, and that removes much of the repeated white space too, so the gain after compression is smaller than the gain you see here. The gzip figure on this page shows the size of both versions.
Can it merge rules, remove unused CSS or reorder properties?
No, and that is deliberate. Merging or reordering rules can change which rule wins in the cascade, and finding unused CSS needs your HTML and JavaScript. This tool only removes comments and white space and shortens values, so the cascade stays exactly as you wrote it.
Is my CSS sent anywhere?
No. The CSS is processed by JavaScript in this page and is never uploaded, logged or stored. You can disconnect from the internet after the page loads and it will still work.
Sources & references
Updated Oct 13, 2026