1. The hover states died the day the reformat shipped
A stylesheet that had been packed away for years and nobody touched: the first thing you do when you take it over is reformat it. The 243 character input beautified into 291 characters over 26 lines, one property per line, easier on the eye than before. The feedback landed the same day it went live: buttons had no hover state, and the prefix icons on list items were gone as well.
Line by line through the output, the root cause sits on .btn: hover. The original file says .btn:hover; a space appeared behind the colon out of nowhere and the selector stopped matching. In the same block li::before comes back as li: : before. Feed only .btn:hover{opacity:0.8}li::before{content:""}a:focus{outline:none} to the CSS beautifier and minifier and 66 characters turn into 90 across 12 lines, with none of the three pseudo-classes left intact. The sample preloaded on that page already carries this pseudo-class, so a single beautify run reproduces the damage.
2. The beautifier reads characters, not the identity of a colon
A colon in CSS has at least four identities: pseudo-class and pseudo-element, between a property and its value, inside a media feature, inside a string. The beautifier treats all four alike and appends one space after every colon. On a property that space is readability; inside a media condition it happens to stay legal; on a pseudo-class it is a syntax accident; inside quotes it rewrites the content itself. The 69 character @media (max-width:600px){.a{color:red}.b{padding:calc(100% - 4px) 0}} beautifies into 87 characters over 11 lines: the condition colon gets a space and a blank line follows the opening brace.
The damage in the JS beautify and minify article sat in semicolons and line breaks, where no meaning binds an identifier to the colon beside it. A CSS pseudo-class survives only because that colon stays tight.
Fig. 1: characters and lines for the pseudo-class sample, before and after
3. The indent control: three settings, byte for byte identical
Nothing is indented, so the reflex is to go change the indent setting, which really does list 2 spaces, 4 spaces and Tab. Yet the same sample comes out at 291 characters and 26 lines under all three, every line flush at column 0, with no difference down to the byte: the character loop does compute an indent, one trim per line wipes all of it, and the closing pass writes the depth back as a value that is always 0. Switch to minify and that control only dims (measured opacity 0.5); the dropdown is never disabled, so changing it still changes nothing.
4. Minify is the conservative one: it never touches calc spacing
Both assumptions fail. The first is calc(): .box{width:calc(100% - 20px);padding:calc( 10px - 5px )} goes from 60 characters down to 56, and not one space around the minus sign is lost, while the extra ones are normalized. It will not add what you forgot either, so the invalid calc(100%-20px) ends at 27 characters with nothing rewritten.
The second is IE hacks: .ie6{*zoom:1;_height:1%;width:10px} leaves as 35 characters unchanged, because the leading * and _ are not swallowed as illegal declarations. !important behaves the same way: red !important and none!important come out mixed exactly as written, and 47 characters stay 47 characters.
Removing every whitespace fails too: minify only drops the blanks and line breaks beside braces, colons and commas, and the single place it rewrites visible content is a string, where the 21 character .s{content:"x, y; z"} compresses to 19 characters.
5. /*! */ gets no privilege, and one checkbox decides its fate
Bundlers usually treat /*! */ as a preserved comment. This build makes no exception: it enters the same matching branch as an ordinary comment, and whether it survives rests entirely on the checkbox that is on by default. /*! keep me: v1.0; license */ together with an ordinary comment and body{color:red} is 64 characters in total; clear the box and minify cuts it to 15 characters, 76.6% smaller, license header gone along with it. Leave the box checked and the result is 61 characters, only 4.7% down, while the inside of the comment is still rewritten, so keep me: v1.0 comes back as keep me:v1.0. That is the same reading as the missing comment case in the SQL beautify article: the checkbox decides presence and nothing else.
6. Semicolons in strings and url() are read as declaration separators
The beautifier cuts a second time exactly where it should not. The 56 character .i{background:url("data:image/png;base64,iVBORw0KGgo=")} beautifies into 65 characters: the base64 payload snaps in two at the semicolon, and data: picks up a space as well. The 49 character protocol address is not spared, and returns as url(https: //www.uutools.com/a.png). For an inline icon, beautifying does not mean uglier layout; it means the whole asset is gone.
7. Beautifying is not idempotent, minifying is
Paste the output back in and run it once more, and the count climbs again: on the default sample the first pass ends at 291, the second at 310, and the extra 19 is exactly the number of colons in the output, while a third pass still reads 310. The calc example runs 64 to 67 and then 67 again, and the @media example runs 87 to 93 and then 93 again. The four minify samples settle on their first run, and 243 characters stays 243 through three passes.
Fig. 2: the three indent settings and two repeat beautify passes
8. Size gains are a separate account, and the stat bar is not a byte table
A stylesheet of 2,000 rules and 91,780 characters minifies down to 89,780 characters, only 2.2% smaller, in 0.8 ms; the same input beautifies to 107,779 characters over 10,000 lines, 17.4% heavier, in 211.6 ms. When the input has little spare whitespace to begin with, minify simply does not have that kind of win.
The stat bar needs its own conversion: it counts UTF-16 code units rather than bytes, so a sample with Chinese reports 25 characters where UTF-8 really holds 33 bytes. In beautify mode the change is a net gain, that 243 character input shows +19.8% in red, no change at all prints as +0%, and when something fails the result of 0 characters renders as a green -100.0%.
| Symptom | What to check first | Measured numbers |
|---|---|---|
| Hover states stop working | The space added behind selector colons | 66 characters become 90 |
| Indent setting does nothing | Whether the three settings change output at all | 291 characters, 26 lines, flush left |
| Inline icon disappears | Whether the data URI semicolon got wrapped | 56 characters stretch to 65 |
| calc subtraction errors out | Whether the spaces around the minus were ever written | 60 down to 56, 27 unchanged |
Q: How do I spot a split pseudo-class right away?
Watch for the extra space behind a colon: .btn:hover becomes .btn: hover, and li::before becomes li: : before. This build checks nothing, so illegal input still runs through the beautifier with no warning, and lines growing from 1 to 26 does not mean the result works.
Q: Does minify eat the spaces inside calc?
It does not: 60 characters compress to 56 and calc(100% - 20px) passes through as written. It will not add spaces you forgot either, so the invalid calc(100%-20px) is still 27 characters. The spacing in IE hacks and !important is untouched for the same reason; the beautify mode is where things break.
Q: Can this page give me a 4 space indent?
It cannot: all three settings return 291 characters and 26 lines for the same sample, every line flush left. That mode is for reading structure only, so check the pseudo-class and the data URI yourself before you ship.