CSS Minify Tests
Correctness tests for CSS minification tools. Each test provides a CSS input and a single canonical minified output. A tool passes if its output matches exactly.
Summary
| clean-css | csskit | cssnano | csso | esbuild | lightningcss | |
|---|---|---|---|---|---|---|
| v5.3.3 | v0.0.17 | v7.1.2 | v5.0.5 | v0.27.3 | v1.31.1 | |
| Total | 151 / 371 | 114 / 371 | 201 / 371 | 144 / 371 | 177 / 371 | 261 / 371 |
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
| anchor | 1 / 5 | 0 / 5 | 1 / 5 | 1 / 5 | 0 / 5 | 0 / 5 |
| charset | 1 / 2 | 0 / 2 | 1 / 2 | 1 / 2 | 0 / 2 | 1 / 2 |
| colors | 17 / 34 | 20 / 34 | 24 / 34 | 18 / 34 | 22 / 34 | 27 / 34 |
| comments | 4 / 5 | 2 / 5 | 3 / 5 | 3 / 5 | 3 / 5 | 2 / 5 |
| container | 3 / 6 | 2 / 6 | 1 / 6 | 1 / 6 | 1 / 6 | 5 / 6 |
| counter-style | 3 / 3 | 0 / 3 | 3 / 3 | 1 / 3 | 1 / 3 | 1 / 3 |
| duplicates | 15 / 18 | 5 / 18 | 8 / 18 | 14 / 18 | 9 / 18 | 12 / 18 |
| empty-rules | 4 / 4 | 0 / 4 | 4 / 4 | 4 / 4 | 4 / 4 | 4 / 4 |
| escaping | 3 / 12 | 9 / 12 | 3 / 12 | 4 / 12 | 10 / 12 | 10 / 12 |
| font-face | 3 / 6 | 2 / 6 | 3 / 6 | 3 / 6 | 4 / 6 | 5 / 6 |
| gradients | 0 / 5 | 0 / 5 | 0 / 5 | 0 / 5 | 1 / 5 | 4 / 5 |
| import | 0 / 5 | 0 / 5 | 0 / 5 | 0 / 5 | 4 / 5 | 0 / 5 |
| keyframes | 0 / 2 | 0 / 2 | 2 / 2 | 2 / 2 | 2 / 2 | 2 / 2 |
| layer | 1 / 2 | 0 / 2 | 0 / 2 | 0 / 2 | 0 / 2 | 2 / 2 |
| media | 1 / 9 | 1 / 9 | 1 / 9 | 1 / 9 | 1 / 9 | 8 / 9 |
| merging | 7 / 10 | 3 / 10 | 9 / 10 | 6 / 10 | 5 / 10 | 9 / 10 |
| nesting | 0 / 19 | 8 / 19 | 8 / 19 | 0 / 19 | 10 / 19 | 4 / 19 |
| page | 3 / 4 | 3 / 4 | 3 / 4 | 3 / 4 | 3 / 4 | 3 / 4 |
| property | 2 / 2 | 2 / 2 | 2 / 2 | 2 / 2 | 0 / 2 | 2 / 2 |
| scope | 1 / 3 | 0 / 3 | 1 / 3 | 1 / 3 | 1 / 3 | 1 / 3 |
| selectors | 10 / 15 | 3 / 15 | 11 / 15 | 5 / 15 | 8 / 15 | 13 / 15 |
| selectors-advanced | 2 / 13 | 3 / 13 | 3 / 13 | 3 / 13 | 3 / 13 | 3 / 13 |
| shorthands | 29 / 72 | 8 / 72 | 20 / 72 | 21 / 72 | 19 / 72 | 53 / 72 |
| starting-style | 0 / 2 | 2 / 2 | 1 / 2 | 2 / 2 | 2 / 2 | 1 / 2 |
| supports | 3 / 5 | 1 / 5 | 3 / 5 | 3 / 5 | 1 / 5 | 3 / 5 |
| transforms | 0 / 9 | 0 / 9 | 7 / 9 | 0 / 9 | 7 / 9 | 9 / 9 |
| values | 16 / 70 | 18 / 70 | 56 / 70 | 19 / 70 | 34 / 70 | 55 / 70 |
| whitespace | 14 / 19 | 15 / 19 | 15 / 19 | 17 / 19 | 13 / 19 | 15 / 19 |
| zero-units | 8 / 10 | 7 / 10 | 8 / 10 | 9 / 10 | 9 / 10 | 7 / 10 |
| Subtotal | 151 / 371 | 114 / 371 | 201 / 371 | 144 / 371 | 177 / 371 | 261 / 371 |
anchor
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`position-area: center center` is equivalent to `position-area: center`. When both axes are `center`, the second value can be omitted. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`position-area: top center` shortens to `position-area: top`. When one axis is a directional keyword and the other is `center`, the `center` can be omitted as it is the default for the unspecified axis. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsA `@position-try` that only flips the block axis (bottom -> top) is equivalent to the built-in `flip-block` try tactic. The at-rule can be removed and the reference replaced with the keyword, saving the entire block. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsAn empty `@position-try` block with no declarations can be removed entirely. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`position-try-fallbacks: --top, --undefined` can drop `--undefined` when no matching `@position-try --undefined` exists in the stylesheet. Unresolved dashed-ident fallbacks are skipped at runtime and have no effect. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 1 / 5 | 0 / 5 | 1 / 5 | 1 / 5 | 0 / 5 | 0 / 5 |
charset
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`@charset "UTF-8"` is redundant in modern workflows since UTF-8 is the default encoding. It should be stripped. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsOnly the first @charset declaration is meaningful; subsequent @charset rules are dropped. Uses two non-UTF-8 charsets to avoid special-casing UTF-8 removal. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 1 / 2 | 0 / 2 | 1 / 2 | 1 / 2 | 0 / 2 | 1 / 2 |
colors
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`#ffffff` can be collapsed to `#fff` when all digit pairs match. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`#ff0000` is longer than the named keyword `red`. The shorter form should be used. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`rgb(255, 0, 0)` is equivalent to `red` and shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsFully opaque `rgba(0, 0, 0, 1)` can drop the alpha channel and convert to a shorter hex form. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`rgb(210, 180, 140)` equals the named color `tan`. Tests awareness of the full CSS named-color table, not just the obvious primaries. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`#aabbcc` can be collapsed to `#abc`. Same rule as `#ffffff` -> `#fff` but with a non-trivial color. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`rgba(255, 0, 0, 0.5)` is shorter as `#ff000080` using 8-digit hex with alpha channel. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`hsl(0, 100%, 50%)` is pure red. The named keyword `red` is shorter. Conversion applies from hsl color space, not just rgb/hex. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`rgba(0, 0, 0, 0)` is fully transparent. The 4-digit hex `#0000` is the shortest equivalent representation (5 chars vs 11 for `transparent`). Note that 4-digit hex (CSS Color Level 4) may not be emitted by all minifiers -- some produce `transparent` instead, which is correct but not minimal. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
Details`hwb(0 0% 0%)` resolves to pure red (#ff0000) which is shorter as the named color `red`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
Details`rebeccapurple` (#663399) is shorter as the 3-digit hex `#639`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
Details`rgb(128, 128, 0)` is #808000, which is shorter as the named color `olive`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
Details`hsl(120, 100%, 25%)` resolves to #008000 which is shorter as the named color `green`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0014
| ||||||
Details`#AABB11` should be lowercased and collapsed to `#ab1`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0015
| ||||||
Details`rgb(143 101 98 / 43%)` can be converted to the shorter 8-digit hex `#8f65626e`. The alpha 43% maps to byte 0x6E (110). This is the standard 8-bit quantization browsers apply internally, making the conversion safe. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0016
| ||||||
DetailsThe modern space-separated `rgb(255 0 0 / 1)` syntax with full opacity should minify to the shortest equivalent named color `red`, dropping the alpha channel. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0017
| ||||||
Details`hsl(120 100% 50% / 0.5)` resolves to fully saturated green at 50% opacity. This can be converted to the shorter 8-digit hex `#00ff0080`. The alpha 0.5 maps to byte 0x80 (128) under standard 8-bit quantization. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0018
| ||||||
Details`color-mix(in srgb, red 50%, blue 50%)` can be resolved at build time. The 50/50 sRGB mix of red (255,0,0) and blue (0,0,255) is (128,0,128) = `purple`. Minifiers should flatten color-mix() with static arguments to the shortest form. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0019
| ||||||
DetailsWhen `color-mix()` omits percentages (defaulting to 50%/50%) with known color arguments, minifiers can resolve the mix at build time. `color-mix(in srgb, red, blue)` is the same 50/50 mix as the explicit form, yielding (128,0,128) = `purple`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0020
| ||||||
Details`color(from red srgb r g b / 0.5)` passes all channels through from `red` unchanged, so it resolves to `srgb(1 0 0 / 0.5)` which is `#ff000080`. A minifier that can evaluate static relative color expressions should fold this. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0021
| ||||||
Details`none` in `rgb(none 128 0)` means "missing channel". Outside an interpolation context (like `color-mix`), missing channels resolve to `0`. So this is `rgb(0 128 0)` = `#008000` = `green`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0022
| ||||||
Details`#ff00007a` has alpha `7a` (not `77`), so it cannot be shortened to 4-digit hex `#f007`. A minifier that naively pairs digits would produce the wrong alpha. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0023
| ||||||
Details`purple` is `#800080` -- 6 chars vs 7 for hex, and the digits don't pair so it can't shorten to 3-digit hex either. A minifier must not convert to hex here. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0024
| ||||||
DetailsIn interpolation contexts like `color-mix`, a `none` (missing) channel is replaced by the corresponding channel from the other color before mixing. `rgb(none 0 0)` mixed 50/50 with `rgb(200 0 0)` yields `rgb(200 0 0)` = `#c80000` because the missing R channel adopts 200 from the other side. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0025
| ||||||
Details`currentColor` is a runtime keyword that inherits the computed `color` value. It cannot be replaced with a static color at build time because the inherited value depends on the DOM context. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0026
| ||||||
Details`oklch()` values can have their numbers minified (leading zero removal) but must not be converted to sRGB hex since the oklch gamut exceeds sRGB. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0027
| ||||||
Details`oklab()` values can have their numbers minified (leading zero removal) but must not be converted to hex since oklab colors may fall outside the sRGB gamut. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0028
| ||||||
Details`color-mix(in srgb, red, red)` mixes a color with itself at equal proportions. The result is always the original color regardless of the interpolation space. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0029
| ||||||
Details`color-mix(in oklch, red 50%, blue 50%)` can be resolved at build time to `oklch(53.9985% .285449 326.643)`. A minifier that resolves the mix must do so in oklch space -- mixing in srgb produces a different color. Keeping the result in oklch avoids lossy gamut mapping to sRGB hex. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0030
| ERR | |||||
Details`color(display-p3 1 0 0)` is a P3 red that cannot be represented in sRGB. Converting to hex or rgb would clamp the value and lose the wider gamut intent. The color function and space must be preserved. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0031
| ||||||
Details`rgba(255, 255, 255, 1.0)` inside a `color-mix()` with a `var()` second argument can still be shortened to `#fff`. The var() prevents resolving the mix, but the literal color is independently minifiable. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0032
| ||||||
Details`hsl(0, 100%, 50%)` inside a `color-mix()` with a `var()` second argument can still be shortened to `red`. The var() prevents resolving the mix, but each literal color argument is independently minifiable. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0033
| ||||||
DetailsPer CSS Color 5, `oklab` is the default interpolation method for `color-mix()` when none is specified. `in oklab` can be elided, saving 9 bytes. Browsers already support the omitted form. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0034
| ||||||
Details`blue` (4 chars) converts to `#00f` (4 chars) which looks like a no-op, but `#` is an unambiguous token start so the preceding space can be dropped: `1px solid#00f` saves 1 byte over `1px solid blue`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 17 / 34 | 20 / 34 | 24 / 34 | 18 / 34 | 22 / 34 | 27 / 34 |
container
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsRemove whitespace inside `@container` query while preserving the container name and condition. The space between name and `(` is required. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsAn `@container` rule with no child rules has no effect and can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`style()` container queries must be preserved. Whitespace around `:` inside the condition can be removed but the `style()` function itself must not be stripped as unknown. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`@container (min-width: 700px)` can be shortened to `@container (width>=700px)` using range syntax. Container queries support the same range forms as media queries. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`@container (max-width: 500px)` can be shortened to `@container (width<=500px)` using range syntax. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`@container sidebar (min-width: 700px)` can use range syntax for the condition while preserving the container name: `@container sidebar (width>=700px)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 3 / 6 | 2 / 6 | 1 / 6 | 1 / 6 | 1 / 6 | 5 / 6 |
counter-style
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsBasic whitespace minification inside a `@counter-style` rule. The space between the at-keyword and the name must be preserved (unlike `@page`), but all other internal whitespace is removable. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsAn empty `@counter-style` with no descriptors can be removed entirely. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`symbols: "(" ")"` must keep quotes. Parentheses are not valid unquoted ident tokens and stripping quotes would produce a parse error. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 3 / 3 | 0 / 3 | 3 / 3 | 1 / 3 | 1 / 3 | 1 / 3 |
duplicates
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsWhen a property is declared twice in the same rule, the last value wins. The earlier duplicate should be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsWhen two adjacent rules share the same selector and the later one completely overrides the earlier, the earlier rule can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsWhen a later rule completely overrides an earlier rule with the same selector, the earlier rule should be removed even with other rules between them. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsDuplicate selectors in a selector list should be deduplicated. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
DetailsThe plain `1rem` fallback and `env()` declaration are progressive enhancement. Removing the "duplicate" breaks browsers that don't support `env()`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
DetailsWhen a property is declared with `!important` and then redeclared without it, the non-important declaration loses and should be removed. The `!important` declaration always wins regardless of order. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
DetailsWhen two rules have the same selector and identical declarations, the duplicate rule is fully redundant and should be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
DetailsWith a modern browserslist target, `-webkit-transform` is unnecessary because all target browsers support unprefixed `transform`. The prefix is dead code. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
DetailsDuplicate compound/complex selectors within a selector list should be deduplicated, including selectors beyond simple type selectors. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
DetailsTwo rules with the same selectors in different order and identical declarations are equivalent. Remove the duplicate by normalizing selector order. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
Details`.foo .bar{...}` and `.foo { .bar{...} }` resolve to the same selector. When the declarations are identical, the duplicate should be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
DetailsWhen a later rule for the same selector contains all declarations of an earlier rule plus additional ones, the earlier rule is redundant and can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
DetailsWhen a custom property has both a normal and `!important` declaration, the `!important` one wins regardless of order. The normal declaration is dead code. Note the space before `!important` is part of the syntax, not the value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0014
| ||||||
Details`border-top: 1px solid blue` followed by `border-top: 2px solid red` is a duplicate declaration. The last one wins and the first can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0015
| ||||||
Details`border-top` is physical and `border-block` is logical. In `horizontal-tb` writing mode `border-block` maps to top/bottom, but in vertical writing modes it maps to left/right. Removing `border-top` would change rendering in some writing modes. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0016
| ||||||
Details`margin-left` is physical and `margin-inline-start` is logical. In LTR `margin-inline-start` maps to `margin-left`, but in RTL it maps to `margin-right`. Both declarations interact via cascade order and writing mode, so removing either changes rendering in some configurations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0017
| ||||||
Details`padding-top` is physical and `padding-block-start` is logical. In `horizontal-tb` they resolve to the same edge, but in vertical writing modes `padding-block-start` maps to `padding-left` or `padding-right`. Removing either declaration changes rendering in some writing modes. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0018
| ||||||
Details`inset-block-start` is logical and `top` is physical. In `horizontal-tb` they resolve to the same edge, but in vertical writing modes `inset-block-start` maps to `left` or `right`. Removing either changes rendering in some writing modes. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 15 / 18 | 5 / 18 | 8 / 18 | 14 / 18 | 9 / 18 | 12 / 18 |
empty-rules
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`a {}` contains no declarations and should be removed entirely. Empty rules waste bytes and have no effect on rendering. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsA rule containing only a comment has no declarations and should be removed. Comments are stripped during minification so the rule body becomes empty. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsAn `@media` block with no rules inside should be removed entirely. It has no effect on rendering. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsAn empty nested rule (`& b {}`) inside a parent should be removed while preserving the parent's own declarations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 4 / 4 | 0 / 4 | 4 / 4 | 4 / 4 | 4 / 4 | 4 / 4 |
escaping
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`\66 oo` is a CSS escape sequence for `foo`. Minifiers should resolve escape sequences in identifiers to their plain UTF-8 equivalents when safe. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`'\66 oo'` should resolve the escape to `"foo"`. Tests both escape resolution within string values and normalization from single to double quotes. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`.\66\6f\6f` encodes each letter of `foo` as a separate hex escape. All three can be resolved to plain ASCII, producing `.foo`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`\2d foo` encodes a hyphen-minus followed by `foo`, producing `-foo`. The hyphen is valid mid-identifier so the escape can be resolved to a literal `-`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`hr\65 f` uses a hex escape for `e` inside the attribute name, producing `href`. The escape can be resolved to a plain ASCII character. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`.\31 23` is the class selector `.123`. The leading digit must remain escaped because bare `123` is not a valid CSS identifier start. A minifier that resolves this to `.123` would produce an invalid selector. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`"\a"` is a CSS escape for a newline character (U+000A). It cannot be replaced with a literal newline inside the string, as that would terminate the string. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`.\@` escapes the `@` sign to use it in a class name. The escape must be preserved because `@` unescaped is not valid in an identifier. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`#\66 oo` is the ID selector `#foo` with a hex escape for `f`. The escape can be resolved since `foo` is a valid identifier. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
Details`a.\62 ar` is `a.bar` with a hex escape for `b`. Escape resolution applies in compound selectors (element + class). Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
Details`\63 olor` encodes the `c` in `color` as a hex escape. Minifiers should resolve escape sequences in property names to their plain equivalents. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
Details`--\66 oo` encodes `f` as a hex escape in a custom property name, resolving to `--foo`. The same escape appears in `var(--\66 oo)` and must resolve consistently. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 3 / 12 | 9 / 12 | 3 / 12 | 4 / 12 | 10 / 12 | 10 / 12 |
font-face
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`@font-face` blocks must be preserved with whitespace stripped. This tests basic whitespace removal without any string or URL optimizations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`font-family: "Custom"` can be unquoted to `font-family: Custom` when the value is a valid CSS identifier. This does not apply to names that are CSS-wide values or contain special characters. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsQuotes inside `url()` can be removed when the URL contains no special characters (whitespace, parentheses, or single/double quotes). `url("font.woff2")` becomes `url(font.woff2)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsThe `format()` function in `@font-face` `src` accepts both string and keyword syntax per CSS Fonts 4. `format("woff2")` and `format(woff2)` are equivalent, so quotes can be safely stripped. Whitespace between `url()` and `format()` can also be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
DetailsUnquoting `"serif"` produces the generic family keyword `serif`, which refers to the browser default serif font -- not a custom font named "serif". Quotes must be preserved when the family name matches a generic keyword. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`U+0000-00FF` can be shortened to `U+??` using wildcard notation. The `?` replaces trailing hex digits that cover the full 0-F range, and leading zeros in the prefix can be dropped. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 3 / 6 | 2 / 6 | 3 / 6 | 3 / 6 | 4 / 6 | 5 / 6 |
gradients
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`linear-gradient(to bottom, ...)` can omit the direction since `to bottom` (180deg) is the default. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`linear-gradient(180deg, ...)` is equivalent to the default direction and can be omitted. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`to right` can be replaced with `90deg` which is shorter. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`0%` on the first stop and `100%` on the last stop are defaults and can be removed. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`ellipse at center` is the default for radial-gradient and can be omitted entirely. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 0 / 5 | 0 / 5 | 0 / 5 | 0 / 5 | 1 / 5 | 4 / 5 |
import
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`@import url("foo.css")` can be shortened to `@import"foo.css"`. The CSS spec allows both forms and the string form is always shorter. No space needed between `@import` and the string token. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`@import url("foo.css") screen` shortens to `@import"foo.css"screen`. The string form removes the url() wrapper and no space is needed between the closing quote and the media query keyword. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`@import url(foo.css)` shortens to `@import"foo.css"`. Even when the url() value is already unquoted, the string form is shorter because it removes the `url(` and `)` wrapper (5 chars) and adds only 2 quote chars. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`@import url("foo.css") layer` shortens to `@import"foo.css"layer`. The layer keyword follows the import URL and no space is needed after the closing quote. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`@import url("foo.css") layer(base) supports(foo: bar)` removes url() wrapper, removes spaces between the closing `)` and next keyword/function, and removes whitespace inside the supports() condition. Uses an unknown property so minifiers cannot elide the supports() condition. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 0 / 5 | 0 / 5 | 0 / 5 | 0 / 5 | 4 / 5 | 0 / 5 |
keyframes
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsThe `100%` keyframe stop can be replaced with the shorter `to` keyword. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`from` becomes `0%` and `100%` becomes `to` since these are shorter representations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 0 / 2 | 0 / 2 | 2 / 2 | 2 / 2 | 2 / 2 | 2 / 2 |
layer
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsDuplicate `@layer` declarations can be deduplicated since layer order is established by first occurrence. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsLayer ordering is determined by first appearance of the layer name, not by physical position of rule blocks. Two `@layer base` blocks separated by `@layer utilities` can be merged because layer precedence is unchanged. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 1 / 2 | 0 / 2 | 0 / 2 | 0 / 2 | 0 / 2 | 2 / 2 |
media
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsStrip whitespace inside a basic `@media` block with nested rules. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsNested `@media` rules should be minified but NOT flattened into a single rule. Merging can change cascade behavior in edge cases. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`@media all and (condition)` is equivalent to `@media (condition)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsAdjacent @media blocks with the same query should be merged into one. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`(min-width: 768px)` can be shortened to `(width>=768px)` using Media Queries Level 4 range syntax. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`(max-width: 1024px)` can be shortened to `(width<=1024px)` using Media Queries Level 4 range syntax. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`(min-height: 600px)` can be shortened to `(height>=600px)` using Media Queries Level 4 range syntax. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`(max-height: 900px)` can be shortened to `(height<=900px)` using Media Queries Level 4 range syntax. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`(min-width: 768px) and (max-width: 1024px)` can be collapsed into a single range condition `(768px<=width<=1024px)`, eliminating the `and` keyword and one pair of parentheses. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 1 / 9 | 1 / 9 | 1 / 9 | 1 / 9 | 1 / 9 | 8 / 9 |
merging
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsAdjacent rules sharing the same selector can be merged into one rule with combined declarations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsAdjacent rules with identical declarations can merge their selectors into a comma-separated list. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsAdjacent @media rules with the same query can be merged into a single @media block. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsAn @media rule with no content should be removed entirely. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
DetailsWhen adjacent rules share some declarations, the common part can be factored out. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
DetailsWhen two @keyframes share the same name, only the last definition is kept. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
DetailsMerging `.foo{color:red}` and `.bar{all:unset;color:red}` into `.bar,.foo{color:red}.bar{all:unset}` is unsafe because `all:unset` resets `color`, so the merged color declaration would be overridden. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
DetailsMerging two identical `@media (width >= 1px)` blocks that have intervening rules between them changes the cascade order. The intervening `a{color:green}` must remain between the two @media blocks so it correctly overrides the first block's `color:red`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
DetailsMerging `.foo{color:red}` and `.bar{all:initial;color:red}` into `.bar,.foo{color:red}.bar{all:initial}` is unsafe because `all:initial` resets `color` to its initial value, so the merged color declaration would be overridden. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
DetailsMerging `.foo{color:red}` and `.bar{all:revert-layer;color:red}` into `.bar,.foo{color:red}.bar{all:revert-layer}` is unsafe because `all:revert-layer` rolls back `color` to the previous cascade layer, so the merged color declaration would be overridden. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 7 / 10 | 3 / 10 | 9 / 10 | 6 / 10 | 5 / 10 | 9 / 10 |
nesting
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsA nested style rule inside a parent rule should be minified in place, preserving the nesting structure while removing whitespace. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`&:hover` inside a parent rule must be preserved as-is. The `&` refers to the parent selector and appending `:hover` creates a compound match. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`&.bar` refines the parent selector, matching elements that match both `.foo` and `.bar`. The compound form must be preserved during minification. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`> .bar` inside a parent rule uses a relative selector (implicit `&`). The child combinator form without an explicit `&` must be preserved. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
DetailsThree levels of nesting (`figure > figcaption > p`) must all be preserved and minified correctly without flattening. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
DetailsA conditional `@media` rule nested inside a style rule should be minified in place. The space after `@media` can be removed when the condition starts with `(`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`& .bar` is equivalent to `.bar` in a nesting context because a nested selector without `&` implies a descendant relationship. The explicit `&` is redundant and can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`&&` equals `.foo.foo`, doubling specificity. Must not collapse to a single `&`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`.parent &` matches `.parent .foo` -- the `&` is not at the start of the selector. This form must be preserved; it cannot be simplified. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
DetailsThree flat rules sharing `.nav` as parent combine into a single nested rule, eliminating repeated selector text. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
Details`a { ... } a:hover { ... }` is shorter when nested as `a{...;&:hover{...}}`, eliminating the repeated `a` selector. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
Details`.card { ... } .card > .title { ... }` is shorter when nested using a relative child selector: `.card{...;>.title{...}}`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
DetailsWhen a parent rule has no declarations of its own, the nested child can be flattened into a single descendant selector. `a { b { color: red } }` becomes `a b{color:red}`, eliminating the empty wrapper. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0014
| ||||||
Details`a { > b { color: red } }` can be flattened to `a>b{color:red}` when the parent has no own declarations. The relative child selector resolves to a direct child combinator. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0015
| ||||||
Details`a { + b { color: red } }` can be flattened to `a+b{color:red}`. The relative next-sibling selector resolves to the adjacent sibling combinator when the parent wrapper has no declarations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0016
| ||||||
Details`a { ~ b { color: red } }` can be flattened to `a~b{color:red}`. The relative subsequent-sibling selector resolves to the general sibling combinator when the parent has no own declarations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0017
| ||||||
DetailsWhen a parent has no own declarations but multiple nested children, keeping the nesting is shorter than flattening because the parent selector only appears once instead of being repeated for each child rule. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0018
| ||||||
Details`a { &:hover { color: red } }` can be flattened to `a:hover{color:red}` when the parent has no own declarations. The `&` resolves to the parent selector, producing the compound `a:hover`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0019
| ||||||
DetailsTwo identical `.bar` rules nested inside `.foo` should collapse to one, then flatten to `.foo .bar{...}` since there are no other rules in the parent. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 0 / 19 | 8 / 19 | 8 / 19 | 0 / 19 | 10 / 19 | 4 / 19 |
page
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsBasic whitespace removal in a `@page` rule. The space between `@page` and `{` can be removed, and internal whitespace is minified as usual. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`@page :first` targets the first page. Whitespace between the pseudo-class and the opening brace can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsAn empty `@page {}` rule with no declarations can be removed entirely. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`@page` can contain margin at-rules like `@top-center`. Whitespace is removed inside both the outer and nested at-rule blocks. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 3 / 4 | 3 / 4 | 3 / 4 | 3 / 4 | 3 / 4 | 3 / 4 |
property
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsRemove whitespace inside `@property` while preserving the descriptor values. The `syntax` string and `initial-value` must not be altered. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsAll three descriptors (`syntax`, `inherits`, `initial-value`) are required and must not be removed or altered. The `syntax` string quotes are required. Changing `inherits` silently breaks inheritance behavior. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 2 / 2 | 2 / 2 | 2 / 2 | 2 / 2 | 0 / 2 | 2 / 2 |
scope
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsBasic whitespace removal in `@scope`. The space between `@scope` and the opening parenthesis can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`@scope (.card) to (.card .content)` uses a scope limit. Whitespace around the parentheses can be removed but the space between `to` and `(` must be preserved to avoid `to(` being tokenized as a function token. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsAn empty `@scope` block with no rules can be removed entirely. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 1 / 3 | 0 / 3 | 1 / 3 | 1 / 3 | 1 / 3 | 1 / 3 |
selectors
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`2n+1` is the definition of `odd`. The keyword form is shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`2n+0` simplifies to `2n`. The `+0` offset is redundant. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ERR | |||||
Details`+5` is the same as `5`. The redundant positive sign should be stripped. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`0n+3` simplifies to just `3`. The zero-step term is redundant. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`2n` is already the shortest form. Unlike `2n+1` -> `odd`, there is no shorter keyword for `2n` (even is same length). Minifiers should preserve `2n` as-is. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`:nth-child(1)` is equivalent to `:first-child`, which is shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`:nth-last-child(1)` is equivalent to `:last-child`, which is shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`:nth-child(1n)` (equivalently `:nth-child(n)`) matches every child element, so the pseudo-class can be removed entirely. `a:nth-child(1n)` becomes just `a`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`:nth-of-type(1)` is equivalent to `:first-of-type` and the latter is shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
Details`:nth-last-of-type(1)` is equivalent to `:last-of-type` and the latter is shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
Details`::before` can be shortened to `:before` for CSS2.1 pseudo-elements. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
DetailsThe `*` selector must be preserved as-is, not removed or altered. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
Details`*#id` is equivalent to `#id`. The universal selector is implied. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0014
| ||||||
DetailsQuotes around attribute values can be removed when the value is a valid identifier. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0015
| ||||||
Details`::view-transition-group()` is a modern pseudo-element and must NOT be shortened to a single colon. The `::` -> `:` shortening is only valid for CSS2.1 pseudo-elements (`::before`, `::after`, etc.). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 10 / 15 | 3 / 15 | 11 / 15 | 5 / 15 | 8 / 15 | 13 / 15 |
selectors-advanced
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`:is(a, b)` can be decomposed to `a,b` when all selectors are widely supported and share the same specificity. This is safe because `:is()` takes the highest specificity of its arguments, which equals each individual selector here. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`:is(#a, .b)` cannot be decomposed to `#a,.b` because `:is()` takes the highest specificity of its arguments. Both `.b` and `#a` match with `(1,0,0)` inside `:is()`, but decomposed `.b` would only have `(0,1,0)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsWhitespace inside `:has()` around combinators can be removed, same as regular selector lists. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsWhitespace inside `:where()` around the selector list commas can be removed. `:where()` itself must not be replaced with `:is()` as they differ in specificity (`:where()` is zero-specificity). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
DetailsOn form elements `:valid` and `:invalid` are a complete partition -- every input is one or the other. So `input:not(:invalid)` can be replaced with the shorter `input:valid`. This only holds when the type selector restricts to elements that participate in constraint validation. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
DetailsEvery element has exactly one directionality -- `ltr` or `rtl`. The two values are a complete partition, so `:not(:dir(ltr))` is equivalent to `:dir(rtl)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`:not(:not(X))` is logically equivalent to `X`. The double negation can be removed, producing a shorter selector. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
DetailsOn form-associated elements `:enabled` and `:disabled` are a complete partition. `input:not(:enabled)` can be replaced with the shorter `input:disabled`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
DetailsOn form-associated elements `:required` and `:optional` are a complete partition. `input:not(:required)` can be replaced with `input:optional`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
DetailsOn hyperlink elements (`<a>`, `<area>`, `<link>` with href) `:link` and `:visited` are a complete partition. `a:not(:link)` can be replaced with the shorter `a:visited`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
Details`:any-link` is equivalent to `:is(:link, :visited)` and is shorter. It matches any element that is a hyperlink source anchor (unvisited or visited). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
DetailsWhen `:is()` restricts to form-associated elements, `:required` and `:optional` are a complete partition. `:is(textarea, input):not(:required)` can be replaced with `:is(textarea, input):optional`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
Details`h1,h2,h3,h4,h5,h6` can be replaced with `:heading` per CSS Selectors Level 5. The `:heading` pseudo-class matches any element with a heading level. Its specificity is that of a class. No browser implements this yet. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 2 / 13 | 3 / 13 | 3 / 13 | 3 / 13 | 3 / 13 | 3 / 13 |
shorthands
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`margin: 10px 10px 10px 10px` collapses to `margin:10px` when all four values are identical. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`margin: 10px 20px 10px 20px` collapses to `margin:10px 20px` when top/bottom and left/right pairs match. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`margin: 10px 20px 30px 20px` collapses to `margin:10px 20px 30px` when left equals right. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`background: none` and `background: 0 0` are equivalent. Both reset all background longhands to initial values -- `0 0` is parsed as `background-position` and all omitted longhands (including `background-image`) reset to their initial values. `0 0` is one byte shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`border: 1px solid #000000` shortens the hex color to `#000` and removes the space before `#` since `#` unambiguously starts a hash token -- no whitespace is needed to separate it from the preceding keyword. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`inset: 0px 0px 0px 0px` collapses to `inset:0`. Combines 4-to-1 shorthand collapse with zero-unit stripping. The `inset` property follows the same pattern as `margin`/`padding`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`padding: 10px 10px 10px 10px` collapses to `padding: 10px` when all four values are identical. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`overflow-x` and `overflow-y` with the same value can be combined into `overflow` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`row-gap` and `column-gap` with the same value can be combined into `gap` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
Details`flex-grow`, `flex-shrink`, and `flex-basis` can be combined into `flex` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
Details`outline-width`, `outline-style`, and `outline-color` can be combined into `outline` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
DetailsAll four `border-*-radius` longhands with the same value collapse into `border-radius` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
DetailsIndividual `margin-top/right/bottom/left` declarations collapse into `margin` shorthand with symmetric 2-value form. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0014
| ||||||
Details`text-decoration-line/style/color` collapse into `text-decoration` shorthand, omitting `solid` (the default style). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0015
| ||||||
DetailsFour padding longhand properties collapse to `padding` shorthand with value dedup. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0016
| ||||||
DetailsAll 12 border longhand properties collapse to a single `border` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0017
| ||||||
DetailsWhen top equals bottom and right equals left, padding collapses from 4 values to 2. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0018
| ||||||
DetailsWhen left equals right, the 4th value can be dropped. Top/bottom differ so 3 values remain. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0019
| ||||||
Detailsborder-radius follows the same top-right-bottom-left collapsing rules as margin/padding. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0020
| ||||||
DetailsBoth horizontal and vertical radii have identical values across all 4 corners, each side collapses to 1 value. The `/` separator must be preserved. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0021
| ||||||
DetailsThe `inset` shorthand follows the same collapsing rules as margin/padding. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0022
| ||||||
DetailsWhen both values in a 2-value margin are identical, collapse to a single value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0023
| ||||||
DetailsWhen align-items and justify-items are the same, they merge into a single-value `place-items`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0024
| ||||||
DetailsWhen align-content and justify-content are the same, they merge into a single-value `place-content`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0025
| ||||||
DetailsWhen align-self and justify-self are the same, they merge into a single-value `place-self`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0026
| ||||||
DetailsWhen row-gap and column-gap differ, they merge into a 2-value `gap` shorthand (row then column). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0027
| ||||||
Detailscolumn-width and column-count merge into the `columns` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0028
| ||||||
Detailslist-style-type, list-style-position, and list-style-image merge into `list-style`. Default values (`disc` type, `none` image) can be omitted. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0029
| ||||||
DetailsBackground longhands merge into `background` shorthand. All properties at their default values except background-color are omitted. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0030
| ||||||
Detailsfont-style, font-weight, font-size, line-height, and font-family merge into `font` shorthand. `bold` optimizes to `700`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0031
| ||||||
Detailstransition-property, transition-duration, transition-timing-function, and transition-delay merge into `transition`. Default values (`ease` timing, `0s` delay) are omitted. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0032
| ||||||
DetailsAll 8 animation longhands merge into `animation` shorthand. Default values (ease, 0s delay, 1 iteration, normal direction, none fill, running) are omitted. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0033
| ||||||
Details`medium` is the default border-width value and can be omitted from the `border` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0034
| ||||||
DetailsDefault background-position (0% 0%), background-repeat (repeat), and background-attachment (scroll) can be omitted from the `background` shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0035
| ||||||
Details`normal` is the default for both font-style and font-weight; both can be omitted from the font shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0036
| ||||||
DetailsColor values within shorthands like `outline` should still be optimized (#ff0000 -> red). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0037
| ||||||
Details`margin: 0 auto 0 auto` collapses to `margin: 0 auto`. The `auto` keyword participates in the same collapsing rules as length values. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0038
| ||||||
Detailsborder-color follows the same top-right-bottom-left collapsing rules as margin/padding. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0039
| ||||||
DetailsWhen row-gap and column-gap are the same in a 2-value `gap`, collapse to a single value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0040
| ||||||
DetailsWhen overflow-x and overflow-y are the same in a 2-value `overflow`, collapse to a single value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0041
| ||||||
Detailsborder-image is declared before border longhands. A minifier collapsing the longhands to `border` must reorder it before `border-image`, since `border` resets border-image to its initial value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0042
| ||||||
DetailsBorder longhands come before border-image. Collapsing longhands to `border` shorthand is safe since border-image already follows and overrides the reset. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0043
| ||||||
DetailsDeclaring border-image then `border` resets border-image to none. The border-image declaration is dead code and can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0044
| ||||||
DetailsBoth border and border-image expressed as longhands. Minifier should collapse each group into its respective shorthand, with `border` ordered before `border-image` to avoid the reset clobbering border-image. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0045
| ||||||
Detailsfont-variant-ligatures is declared before font longhands. A minifier collapsing the longhands to `font` must reorder it before `font-variant-ligatures`, since `font` resets font-variant-ligatures to its initial value (`normal`). Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0046
| ||||||
DetailsFont longhands come before font-feature-settings. Collapsing longhands to `font` shorthand is safe since font-feature-settings already follows and overrides the implicit reset. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0047
| ||||||
DetailsDeclaring font-variant-numeric then `font` resets font-variant-numeric to `normal`. The font-variant-numeric declaration is dead code and can be removed. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0048
| ||||||
DetailsFont longhands and font-kerning are both expressed as longhands. Minifier should collapse the font longhands into `font` shorthand, keeping `font` before `font-kerning` since `font` resets font-kerning to `auto`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0049
| ||||||
Detailsmask-border is declared before mask longhands. A minifier collapsing the longhands to `mask` must reorder it before `mask-border`, since `mask` resets mask-border to its initial value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0050
| ||||||
DetailsMask longhands come before mask-border. Collapsing longhands to `mask` shorthand is safe since mask-border already follows and overrides the implicit reset. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0051
| ||||||
DetailsDeclaring mask-border then `mask` resets mask-border to its initial value. The mask-border declaration is dead code and can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0052
| ||||||
Detailsfont-variation-settings is declared before font longhands. A minifier collapsing the longhands to `font` must reorder it before `font-variation-settings`, since `font` resets font-variation-settings to its initial value (`normal`). Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0053
| ||||||
DetailsMerging padding-top/right/bottom/left into `padding` shorthand is unsafe when values use `var()`. If any variable is undefined or empty, shorthand fallback behavior differs from individual longhands. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0054
| ||||||
Details`font-weight: bold` followed by `font: 14px serif` is dead code because the `font` shorthand resets `font-weight` to `normal`. The longhand can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0055
| ||||||
DetailsMerging `border-width`, `border-style`, `border-color` into `border` shorthand is unsafe when values use `var()`. The variables may expand to multi-value strings (e.g. `--border-width: 0 0 0 1px`) which are valid in longhands but not in the shorthand form. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0056
| ||||||
DetailsWhen one longhand has `!important`, the longhands can still be partially merged into a shorthand followed by the important longhand override. The `!important` declaration wins over the shorthand's reset of the same property. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0057
| ||||||
DetailsA valid fallback does not make merging safe. The fallback only triggers when the property is undefined. If the property is defined with an invalid value (e.g. `--pt: banana`), the fallback is ignored and the entire shorthand declaration fails at computed value time. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0058
| ||||||
DetailsWhen `var()` fallbacks are themselves `var()` references, the final value cannot be statically determined. Merging into shorthand is unsafe because the nested variable may resolve to an invalid or multi-value result. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0059
| ||||||
DetailsA valid fallback does not make merging safe. The fallback only triggers when the property is undefined. If the property is defined with an invalid value, the fallback is ignored and the entire shorthand declaration fails at computed value time. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0060
| ||||||
DetailsIf even one `var()` has an unresolvable fallback (nested `var()`, no fallback, etc.), the longhands cannot be safely merged into `border` shorthand because the runtime value may expand to something invalid in shorthand context. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0061
| ||||||
DetailsWhen each custom property has an `@property` rule constraining its syntax to `<length>`, the value is guaranteed valid at parse time. Invalid values are rejected and fall back to `initial-value`, so shorthand merge is safe. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0062
| ||||||
DetailsWhen each custom property has an `@property` rule constraining its syntax, invalid values are rejected at parse time and fall back to `initial-value`. The variable is guaranteed to produce a single valid component, so shorthand merge is safe. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0063
| ||||||
Details`top: 0; right: 0; bottom: 0; left: 0` merges into `inset: 0`. The `inset` shorthand sets all four physical inset properties and is shorter when all values are equal. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0064
| ||||||
Details`margin-inline-start: 10px; margin-inline-end: 10px` merges into `margin-inline: 10px`. When both logical sides are equal, the two-value form collapses to a single value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0065
| ||||||
Details`position-try-order: normal; position-try-fallbacks: flip-block, --custom` merges into `position-try: flip-block, --custom`. The `normal` order is the initial value and can be omitted in the shorthand. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0066
| ||||||
Details`border-top: 1px solid blue` followed by `border: 2px solid red` is dead code because the `border` shorthand resets all sides including `border-top`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0067
| ||||||
Details`border-block-start: 1px solid blue` followed by `border-block: 2px solid red` is dead code because `border-block` resets both `border-block-start` and `border-block-end`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0068
| ||||||
Details`padding-inline-start: 10px` followed by `padding-inline: 20px` is dead code because `padding-inline` resets both `padding-inline-start` and `padding-inline-end`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0069
| ||||||
Details`margin-top: 10px` followed by `margin: 20px` is dead code because the `margin` shorthand resets all four physical sides. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0070
| ||||||
Details`border-top-width: 1px` followed by `border-width: 2px` is dead code because `border-width` resets all four physical border widths. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0071
| ||||||
Details`border-top-color: blue` followed by `border-top: 2px solid red` is dead code because `border-top` resets `border-top-color`, `border-top-style`, and `border-top-width`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0072
| ||||||
Details`inset-block-start: 10px` followed by `inset-block: 20px` is dead code because `inset-block` resets both `inset-block-start` and `inset-block-end`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 29 / 72 | 8 / 72 | 20 / 72 | 21 / 72 | 19 / 72 | 53 / 72 |
starting-style
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsBasic whitespace removal in `@starting-style`. Defines the initial style for CSS transitions when an element is first displayed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`@starting-style` with `display: none` and `opacity: 0` defines the entry state for a discrete transition. A minifier must not remove this block even though the values appear to match the element's hidden state -- without it the entry animation does not play. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 0 / 2 | 2 / 2 | 1 / 2 | 2 / 2 | 2 / 2 | 1 / 2 |
supports
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsSpaces inside the `@supports` condition parentheses are removable. Uses a property without universal support so the `@supports` wrapper cannot be statically elided. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsAn @supports rule with no content should be removed entirely, like empty style rules. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`display: grid` is supported in all current browsers. The `@supports` wrapper always evaluates to true and can be removed, unwrapping the inner rules. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`display: flex` is universally supported. The `@supports` wrapper can be removed and all inner rules unwrapped to the parent context. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`hanging-punctuation` lacks universal support, so `@supports not` cannot be statically resolved. The wrapper must remain even though the negation might suggest removal. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 3 / 5 | 1 / 5 | 3 / 5 | 3 / 5 | 1 / 5 | 3 / 5 |
transforms
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`translate3d(x, 0, 0)` can be simplified to `translate(x)` since the Y and Z components are zero. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`translate(0, y)` can be simplified to `translateY(y)` when the X component is zero. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`scale(x, x)` can omit the second argument when both axes are identical: `scale(x)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`rotateZ(a)` is equivalent to `rotate(a)` and shorter. The Z axis is the default rotation axis. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`scale3d(x, y, 1)` can be simplified to `scale(x, y)` when the Z component is 1. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`rotate3d(0, 1, 0, a)` is equivalent to `rotateY(a)` and shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`scale(1.5, 1)` only scales the X axis, equivalent to `scaleX(1.5)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
DetailsWhen X and Y are zero, `translate3d` simplifies to `translateZ`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
DetailsRotation around the X axis only simplifies to `rotateX`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 0 / 9 | 0 / 9 | 7 / 9 | 0 / 9 | 7 / 9 | 9 / 9 |
values
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`bold` is equivalent to `700` and shorter as a numeric value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`normal` is equivalent to `400` and shorter as a numeric value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsQuotes inside `url()` are optional when the URL contains no special characters. They can be removed to save bytes. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`1.0000px` should be normalized to `1px`. Trailing fractional zeros are redundant. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`+1.5px` should be normalized to `1.5px`. The explicit `+` sign on positive numeric values is redundant outside of contexts that require it (e.g. `calc()`). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`001` should be normalized to `1`. Leading zeros on integer values are redundant and can be safely stripped. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`url( image.png )` should be trimmed to `url(image.png)`. Leading and trailing whitespace inside unquoted `url()` tokens is insignificant. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`'hello world'` should be normalized to `"hello world"`. CSS allows both single and double quotes for strings; normalizing to one form is valid. Uses `content` to ensure quotes cannot be removed entirely. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`500ms` should be converted to `.5s` when the seconds representation is shorter. The leading zero is also stripped (`0.5s` -> `.5s`). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
Details`12pt` converts to `16px`. Absolute units (pt, pc, cm, mm, in, Q) have fixed ratios to px. Normalizing to px also improves gzip compression by reducing the number of distinct unit strings in the output. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
DetailsSpaces around `+` and `-` operators inside `calc()` must be preserved. Removing them would cause `50vh+10px` to be parsed as a single dimension token, or `100%-20px` to change meaning. This tests that minifiers do not over-strip. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
Details`var(--main-color)` must be preserved as-is. Custom property references cannot be resolved or optimized at minification time since their values are defined at runtime. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
DetailsWhitespace inside `linear-gradient()` around commas and arguments should be stripped. Uses a numeric angle and short hex colors to avoid confounding direction keyword or color conversions. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0014
| ||||||
Details`calc(calc(100% - 20px) + 10px)` should flatten the inner `calc()` and reduce compatible units: `-20px + 10px` = `-10px`, yielding `calc(100% - 10px)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0015
| ||||||
Details`calc(100px * 2)` can be fully resolved to `200px` at compile time since all values are known. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0016
| ||||||
Details`calc(50px + 50px)` can be resolved to `100px` since both operands share the same unit. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0017
| ||||||
DetailsComplex calc expressions with compatible units are partially reduced: px terms are combined while percentage terms are preserved. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0018
| ||||||
Details`0.50000` should be reduced to `.5` by removing trailing zeros and leading zero. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0019
| ||||||
DetailsExtra whitespace inside grid-template-areas strings is collapsed, and consecutive dots (`....`) for unnamed cells are reduced to a single dot. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0020
| ||||||
Details`center center` resolves to `50%` -- when both axes are the same, a single value suffices. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0021
| ||||||
Details`calc(100% / 3)` cannot be statically resolved to a finite decimal without precision loss. Any truncation (e.g. `33.3333%`) introduces measurable rounding error. The calc wrapper must be preserved; only whitespace is removable. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0022
| ||||||
Details`display: block flow` is the two-value syntax equivalent of `display: block`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0023
| ||||||
Details`cubic-bezier(0, 0, 1, 1)` is the functional form of `linear`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0024
| ||||||
Details`cubic-bezier(0.25, 0.1, 0.25, 1)` is the functional form of `ease`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0025
| ||||||
Details`no-repeat no-repeat` collapses to `no-repeat` when both axes are identical. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0026
| ||||||
Details`repeat no-repeat` is equivalent to the `repeat-x` keyword. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0027
| ||||||
Details`0.25turn` equals `90deg`. Degrees are shorter for common turn fractions. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0028
| ||||||
DetailsThe initial value of `min-width` is `auto` (CSS Sizing Level 3), not `0`. `auto` is shorter than `initial` and semantically equivalent. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0029
| ||||||
Details`border: solid 1px red` should be reordered to `border: 1px solid red` (width style color). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0030
| ||||||
Details`flex-flow: wrap row` should be reordered to `flex-flow: row wrap` (direction then wrap). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0031
| ||||||
DetailsQuotes around font-family names can be removed when the name is a valid CSS identifier sequence. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0032
| ||||||
DetailsDuplicate font names in a font-family list can be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0033
| ||||||
Details`display: inline flow-root` is the two-value equivalent of `inline-block`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0034
| ||||||
Details`steps(1, start)` is the functional form of the `step-start` timing keyword. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0035
| ||||||
Details`left top` is equivalent to `0 0` and shorter. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0036
| ||||||
Details`cubic-bezier(0.42, 0, 1, 1)` is the functional form of `ease-in`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0037
| ||||||
Details`cubic-bezier(0, 0, 0.58, 1)` is the functional form of `ease-out`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0038
| ||||||
Details`no-repeat repeat` is equivalent to the `repeat-y` keyword. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0039
| ||||||
DetailsMultiplying a value by 1 has no effect. `calc(100px * 1)` simplifies to `100px`, removing the calc() wrapper entirely. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0040
| ||||||
DetailsAdding zero of the same unit has no effect. `calc(100px + 0px)` simplifies to `100px`, removing the calc() wrapper. Note: a zero term can only be combined with a term of the same unit, not removed outright. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0041
| ||||||
Details`calc(-1 * (-10px))` negates a negative value. The product -1 \* -10px = 10px, fully resolving to a plain length value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0042
| ||||||
DetailsDividing by a reciprocal cancels out. `calc(1 / (1 / 50px))` simplifies back to `50px` because the two inversions undo each other. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0043
| ||||||
DetailsNested additions inside calc() are flattened into a single addition. Two nested calc() sums are merged and all px terms are combined: `10 + 20 + 30 + 40 = 100px`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0044
| ||||||
DetailsWhen a multiplication chain contains multiple plain numbers, they are multiplied together first. `2 * 3` becomes `6`, then `6 * 10px` = `60px`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0045
| ||||||
DetailsMultiplication distributes over addition. `2 * (50px + 25px)` expands to `100px + 50px`, then the like terms combine to `150px`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0046
| ||||||
DetailsTerms with the same unit are combined by adding their values. `calc(50% + 25%)` becomes `75%`, removing the calc() wrapper. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0047
| ||||||
Details`calc(10 / 2)` divides two unitless numbers, yielding `5`. Since line-height accepts unitless numbers, the result is a plain `5` with the calc() wrapper removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0048
| ||||||
Details`calc(50px - 50px)` subtracts identical values. The same-unit terms cancel out: `50 - 50 = 0`. The result is `0` (unitless zero is valid for lengths). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0049
| ||||||
Details`calc(100px * 0)` multiplies a dimension by zero. The result is `0px`, which serializes as `0`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0050
| ||||||
Details`pi` is a numeric constant (~3.14159). `calc(pi * 10px)` resolves the constant then multiplies, yielding `31.4159px`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0051
| ||||||
Details`e` is Euler's number (~2.71828). `calc(e * 10px)` resolves the constant then multiplies, yielding `27.1828px`. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0052
| ||||||
DetailsWhen all arguments to min() are known comparable values, the function can be fully resolved. `min(10px, 20px)` resolves to `10px`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0053
| ||||||
DetailsCompatible units convert to canonical units: `1in` = `96px`. The sum combines `96px + 0px` = `96px`, resolving to a plain length value. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0054
| ||||||
Details`calc(100px)` contains a single numeric value with no operations. The calc() wrapper is unnecessary and should be removed, yielding `100px`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0055
| ||||||
Details`calc(100px / 4)` creates a Product of `100px` and Invert(`4`). The Invert resolves `4` to `0.25`, then the Product yields `25px`. Fully resolved, no calc() needed. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0056
| ||||||
Details`calc(100% - 50px + 0%)` has both percentage and px terms. Like units are combined: `100% + 0%` = `100%`, while `-50px` remains unchanged. The result is `calc(100% - 50px)` -- calc() is preserved because % and px cannot be resolved together at specified-value time. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0057
| ||||||
DetailsCustom property values may be read by JavaScript via `getComputedStyle`, where the serialized form matters. Converting `rgb(0 0 0)` to `#000` inside a custom property changes JS-visible serialization. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0058
| ||||||
Details`--foo: ;` is valid CSS that sets a custom property to an empty value (a single space token). This is used to "reset" inherited custom properties. Discarding this declaration as "empty" changes behavior because `var(--foo, red)` would then use the fallback instead. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0059
| ||||||
DetailsA rule with unrecognized property names is syntactically valid CSS. Minifiers must not discard it -- unknown properties may be meaningful to other tools or future CSS specifications. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0060
| ||||||
DetailsRemoving quotes from `url("image (1).png")` would produce `url(image (1).png)` which is a parse error -- the unquoted form cannot contain `(` or `)`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0061
| ||||||
Details`content: ""` generates a pseudo-element with no text. Removing the declaration or changing the value to `none`/`normal` would prevent the pseudo-element from being generated, which is a semantic change. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0062
| ||||||
DetailsWhen min, preferred, and max are all the same known value, `clamp()` can be replaced with that value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0063
| ||||||
DetailsWhen all arguments to `max()` are static comparable values, the function can be replaced with the largest value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0064
| ||||||
DetailsThe initial value of `opacity` is `1`, which is shorter than `initial`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0065
| ||||||
DetailsThe initial value of `display` is `inline`, which is the same length as `initial`. No replacement saves bytes. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0066
| ||||||
DetailsThe initial value of `z-index` is `auto`, which is shorter than `initial`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0067
| ||||||
DetailsThe initial value of `margin` is `0`, which is shorter than `initial`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0068
| ||||||
DetailsThe initial value of `background-color` is `transparent`, which is longer than `initial`. No replacement saves bytes. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0069
| ||||||
Details`calc(100px + 0%)` must not simplify to `100px`. Although `0%` is numerically zero, it has a different unit type. The browser resolves `%` against the containing block at computed value time, and future animations or transitions could interpolate through non-zero percentage values. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0070
| ||||||
DetailsWhen `@property` declares `syntax: "<color>"`, the value is parsed as a color at parse time. The serialization is well-defined, so `rgb(0 0 0)` can be safely minified to `#000`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 16 / 70 | 18 / 70 | 56 / 70 | 19 / 70 | 34 / 70 | 55 / 70 |
whitespace
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
DetailsRemove newlines, indentation, and spaces around braces and colons. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
DetailsBlank lines between rules must be collapsed. No separator is needed between `}` and the next selector. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
DetailsValues split across lines with tab indentation must collapse correctly. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
DetailsSpaces around commas in selector lists (`a , b`) must be removed. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
DetailsThe semicolon after the last declaration in a rule can be dropped. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`color: red;;` should collapse redundant semicolons. Multiple consecutive semicolons are syntactically valid but wasteful; only one is needed between declarations, and the final one before `}` can also be dropped. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`@media not print` requires a space between `not` and `print`. Without it, `notprint` becomes a single ident token parsed as an unknown media type, changing the query from "not print media" to "unknown media type" which never matches. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`@media screen and (color)` requires spaces around `and`. Without a space before `and`, `screenand` becomes a single ident token (unknown media type). Without a space after `and`, `and(` becomes a function token instead of the `and` keyword followed by `(`, making the query invalid. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
Details`@supports not (display: flex)` requires a space between `not` and `(`. The CSS tokenizer treats `not(` as a function token, not the `not` keyword followed by `(`. This changes the grammar from a negation condition to an invalid/unknown function call, causing the condition to fail. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
Details`@supports (X) and (Y)` requires spaces around `and`. Without a space after `and`, the tokenizer produces a function token `and(` instead of the keyword `and` followed by `(`, causing the entire @supports rule to be dropped by the parser. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0011
| ||||||
DetailsSpaces around `+` inside `calc()` are required by the CSS spec, just like `-`. Without the space, `+20px` is tokenized as a single positive dimension token, leaving two values with no operator, which is invalid and causes the declaration to be silently dropped. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0012
| ||||||
DetailsUnlike `+` and `-`, the `*` and `/` operators in `calc()` do not require surrounding spaces. They are delim tokens that cannot be confused with number signs, so `calc(100%*2)` and `calc(10px/2)` are valid. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0013
| ||||||
DetailsIn `transform: rotate(45deg) scale(2)`, the space between `)` and `scale(` can be removed. The `)` token is always its own token and cannot merge with the following function token, so `rotate(45deg)scale(2)` parses identically. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0014
| ||||||
DetailsIn `background: url(bg.png) no-repeat`, the space between `)` and `no-repeat` can be removed. The `)` token always terminates cleanly and cannot merge with the following ident token, so `url(bg.png)no-repeat` parses identically. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0015
| ||||||
DetailsIn `font: 16px / 1.5 sans-serif`, the spaces around `/` separating font-size from line-height can be removed. The `/` is a delim token that always stands alone, so `16px/1.5` parses identically. Note the space before `sans-serif` must remain because `1.5sans-serif` would become a single dimension token. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0016
| ||||||
DetailsIn `div p`, the space IS the descendant combinator. Removing it produces `divp`, a single type selector for an element named `divp` which matches nothing. The space between simple selectors forming a descendant relationship must always be preserved. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0017
| ||||||
Details`#` unambiguously starts a hash token in CSS, so no whitespace is needed to separate it from a preceding ident or keyword. `solid #fff` becomes `solid#fff`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0018
| ||||||
Details`color: red !important` can drop the space before `!`. The `!` delimiter token is not an ident character so no ambiguity arises when adjacent to the value. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0019
| ||||||
DetailsSpaces around `+` and `-` operators inside `clamp()` are required just like in `calc()`. Stripping them silently breaks the declaration. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 14 / 19 | 15 / 19 | 15 / 19 | 17 / 19 | 13 / 19 | 15 / 19 |
zero-units
| test | clean-css | csskit | cssnano | csso | esbuild | lightningcss |
|---|---|---|---|---|---|---|
0001
| ||||||
Details`0px` equals `0` for length properties. The unit is redundant. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0002
| ||||||
Details`0s` must NOT be simplified to `0`. Unitless zero is invalid for `<time>` values. Stripping the unit breaks transitions and animations. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0003
| ||||||
Details`0%` is not always equivalent to `0` (e.g. in `width`). The unit must be preserved. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0004
| ||||||
Details`padding: 0px 10px 0px 10px` requires both `0px` -> `0` conversion and 4-to-2 shorthand collapse. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0005
| ||||||
Details`0.5em` can be shortened to `.5em`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0006
| ||||||
Details`1.0` can be shortened to `1`. Trailing fractional zeros are redundant. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0007
| ||||||
Details`flex: 0 0 0px` shortens to `flex: 0 0`. When flex-grow and flex-shrink are specified as numbers, the omitted flex-basis defaults to `0%`, which is equivalent to `0px` (both resolve to zero length). Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0008
| ||||||
Details`0deg` must NOT be simplified to `0` in the `rotate` property. Unlike legacy transform functions (where browsers accept unitless zero for compatibility), the individual transform properties reject unitless zero per spec. Stripping the unit produces an invalid declaration. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0009
| ||||||
DetailsIn keyframe selectors, `0%` must not be stripped to bare `0`. A `0` without `%` is not valid as a keyframe selector. The `%` unit must be preserved. Source
Expected
ValidateOutputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
0010
| ||||||
DetailsUnitless zero is invalid for `<flex>` values. `0fr` in grid track sizing must not be stripped to `0`, which would be parsed as a `<length>`. Source
Expected
Outputsclean-css
csskit
cssnano
csso
esbuild
lightningcss
|
||||||
| Subtotal | 8 / 10 | 7 / 10 | 8 / 10 | 9 / 10 | 9 / 10 | 7 / 10 |
comments
0001Details
Standard `/* ... */` comments should be stripped entirely.
Source
Expected
Outputs
clean-css ✓
csskit ✓
cssnano ✓
csso ✓
esbuild ✓
lightningcss ✓
0002Details
A comment embedded within a declaration value (`color: /* inline */ red`) must be removed without breaking the surrounding value.
Source
Expected
Outputs
clean-css ✓
csskit ✓
cssnano ✓
csso ✓
esbuild ✓
lightningcss ✓
0003Details
Comments starting with `/*!` are license/legal markers and must be preserved. Stripping them can cause legal compliance issues.
Source
Expected
Outputs
clean-css ✓
csskit ✗
cssnano ✓
csso ✗
esbuild ✓
lightningcss ✗
0004Details
`--bar: a/**/b` tokenizes as `ident:a` `ident:b` with no whitespace between them. Replacing the comment with a space produces `a b` which is a different token sequence. This matters for `@container style()` queries matching against custom property values.
Source
Expected
Outputs
clean-css ✓
csskit ✗
cssnano ✗
csso ✓
esbuild ✗
lightningcss ✗
0005Details
`@container style(--bar: a/**/b)` uses a comment as a zero-width token separator. Replacing it with a space or removing it entirely changes the token sequence the query matches against, breaking the correspondence with the declaration `--bar: a/**/b`.
Source
Expected
Outputs
clean-css ✗
csskit ✗
cssnano ✗
csso ✗
esbuild ✗
lightningcss ✗