/
githubmirror
/
webpack
Обзор
Документация
Войти
/
githubmirror
/
webpack
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
test/configCases/css/minimize-values/style.css
401 строка
22 KB
Alexander Akait
perf(css): write selectors, An+B and more values in their shortest spelling (#21664)
11 авг 2026, 13:43
Не верифицирован
11 авг 2026, 13:43
4015bbd
Код
Авторство
О чём код?
/* Ported from cssnano's `postcss-convert-values` and `postcss-normalize-whitespace` suites. webpack normalizes a number and rounds it to 6 significant digits, and rewrites a time into the shorter of `ms` / `s` — but only where the engine cannot tell: a zero's unit stays inside `calc()` and on a `flex-basis`, an angle keeps every digit (`rotate()` runs it through trig), and nothing is touched in a `@supports` condition, which tests the declaration rather than applying it. A length keeps its unit unless `convertLengthUnits` is on. */ /*! convert-values: should convert milliseconds to seconds */ .t01 { transition-duration: 500ms } /*! convert-values: should convert milliseconds to seconds (2) */ .t02 { animation: opacity 0ms 1000ms } /*! convert-values: should convert seconds to milliseconds */ .t03 { transition-duration: .005s } /*! convert-values: should convert values in custom properties */ .t04 { --my-variable: 500ms } /*! convert-values: should strip the leading plus */ .t05 { width: +14px } /*! declined: px -> pc/pt/in is exact, but it fires ~10 times in all of Bootstrap and costs as many bytes as it saves once compressed, so it is off by default (`convertLengthUnits`) — as it is in cssnano's default preset */ .t06 { width: 16px } .t07 { width: 120px } .t08 { width: 192px } /*! convert-values: should strip the unit from zero lengths */ .t09 { margin: 0em 0% 0px 0pc } /*! convert-values: ...inside a call whose every number is a length too */ .t09a { transform: translate3d(0px, 1em, 2em) } /*! convert-values: ...however deep the shape nests them */ .t09b { clip-path: inset(0px 1px 0em 2px) } /*! declined: `scale()` takes a `<number>`, so `scale(0px)` is dropped where `scale(0)` is a transform — the rewrite would revive the declaration */ .t09c { transform: scale(0px) } /*! webpack: a zero angle drops its unit where the grammar names <zero> */ .t09d { transform: rotate(0deg) } /*! convert-values: should trim trailing zeros */ .t10 { width: 109.00000000000px } /*! convert-values: should trim trailing zeros (2) */ .t11 { width: 0.00px } /*! convert-values: should trim trailing zeros (3) */ .t12 { width: 100.00% } /*! convert-values: should strip the unit from a zero percentage */ .t13 { opacity: 0% } /*! convert-values: should normalize a bare decimal point */ .t14 { opacity: 1. } .t15 { opacity: .0 } /*! convert-values: should normalize a bare decimal point with a unit */ .t16 { width: 10.px } .t17 { width: .0px } /*! convert-values: should normalize inside calc */ .t18 { width: calc(10.px + .0px) } /*! convert-values: should drop the leading zero */ .t19 { top: 0.25rem } /*! convert-values: should drop the leading zero of a negative number */ .t20 { letter-spacing: -0.1rem } /*! convert-values: should keep the unit's case */ .t21 { font-size: 20PX } /*! convert-values: should trim trailing zeros of a percentage */ .t22 { height: 12.500% } /*! convert-values: should strip zero units per declaration */ .t23 { height: 0em; max-height: 0em } /*! convert-values: should not round by default */ .t24 { right: 6.66667px } /*! convert-values: should drop the leading zero of an opacity */ .t25 { opacity: 0.0625 } /*! normalize-whitespace: should trim whitespace from nested functions */ .t26 { width: calc(10px - ( 100px / var(--test) )) } /*! normalize-whitespace: should trim whitespace from nested functions (uppercase) */ .t27 { width: CALC(10px - ( 100px / var(--test) )) } /*! normalize-whitespace: should trim whitespace from css variables */ .t28 { width: var(--foo, calc(10px + 10px)) } /*! normalize-whitespace: should trim whitespace from env variables */ .t29 { width: env(--foo, calc(10px + 10px)) } /*! normalize-whitespace: should preserve space in custom property */ .t30 { --prop: } /*! normalize-whitespace: should not add space around empty custom property */ .t31 { --prop: } /*! normalize-whitespace: should not trim spaces inside of nested var function */ .t32 { background: var(--my-var, var(--my-background, pink, )) } /*! normalize-whitespace: should not trim spaces inside of var inside calc */ .t33 { height: calc(var(--text-xxxl, ) * var(--text-scale-ratio-up, )) } /*! normalize-whitespace: should not trim spaces inside of var function */ .t34 { border-radius: 10px var(--foobar, ) } /*! normalize-whitespace: should not trim spaces inside of env function */ .t35 { border-radius: env(border-rad, ) } /*! normalize-whitespace: should not trim spaces inside of constant function */ .t36 { border-radius: constant(border-rad, ) } /*! normalize-whitespace: should preserve whitespace after custom property declaration */ .t37 { --foo: bar } /* Cases beyond the upstream suites, covering what webpack's own printer decides. */ /*! webpack: `2n+1` is what `odd` names; the other An+B keep their signs */ .t38:nth-child(2n+1) { color: red } /*! webpack: unicode-range tokenizes as numbers, so it stays verbatim */ @font-face { unicode-range: U+0025-00FF, u+4?? } /*! webpack: scientific notation is left alone */ .t39 { width: 1e3px } /*! webpack: two numbers a rewrite could fuse stay separated */ .t40 { margin: 1.0.5 } /*! webpack: !important loses its leading space */ .t41 { color: red !important } /*! webpack: a required value space collapses to one */ .t42 { margin: 0 auto } /*! webpack: calc() operator spaces are meaningful */ .t43 { width: calc(1px + 2px) } /* A query condition's whitespace is insignificant around its comparisons and its `:` — the same code points that must be kept in a selector (combinators, pseudo-class `:`) and in a value (`calc()` operators). */ /*! webpack: a media feature test */ @media (min-width: 100px) { .t44 { color: red } } /*! webpack: ...with whitespace on both sides */ @media screen and (min-width : 100px) { .t45 { color: red } } /*! webpack: a Media Queries Level 4 range */ @media (width >= 40rem) { .t46 { color: red } } /*! webpack: ...on both sides of the feature */ @media (400px <= width <= 700px) { .t47 { color: red } } /*! webpack: a container query */ @container card (width > 400px) { .t48 { color: red } } /*! webpack: an @supports condition */ @supports (display: grid) { .t49 { color: red } } /*! webpack: ...on a custom property */ @supports (--x: 1) { .t50 { color: red } } /*! webpack: a ratio keeps its slash spacing */ @media (aspect-ratio: 16 / 9) { .t51 { color: red } } /*! webpack: a pseudo-class `:` is not a condition separator */ .t52 :hover { color: red } /*! webpack: a `(…)` inside a value is a calc sub-expression, not a condition */ .t53 { width: calc(10px - ( 100px / var(--x) )) } /*! lightningcss: translate(10px) — translateX's second component defaults to 0 */ .t54 { transform: translateX(10px) } /*! lightningcss: translate(-100%) rotate(3deg) */ .t55 { transform: translateX(-100%) rotate(3deg) } /*! webpack: the argument may be any single component */ .t56 { transform: translateX(calc(1px + 2px)) } /*! webpack: translateY has no one-argument equivalent, so it stays */ .t57 { transform: translateY(10px) } /*! webpack: a second component makes `translateX` invalid — converting it would revive the declaration, so a comma keeps the function */ .t58 { transform: translateX(1px, 2px) } /*! convert-values: a zero length needs no unit (CSS Values 4 §5) */ .t59 { margin: 0px } /*! convert-values: every length unit, and `%` is a different type */ .t60 { width: 0em; height: 0vh; top: 0cm; left: 0Q; right: 0% } /*! webpack: a zero time, angle or `<flex>` still needs its unit */ .t61 { transition-duration: 0s; rotate: 0deg; grid-template-columns: 0fr 1fr } /*! webpack: `flex-basis` keeps it — IE 11 drops a `flex` whose basis has none */ .t62 { flex-basis: 0px } /*! webpack: ...and so does the shorthand carrying one */ .t63 { flex: 1 1 0px } /*! webpack: one component of several */ .t64 { margin: 0px 1px } /*! lightningcss: (width>=1200px) — `min-X: Y` is exactly `X >= Y` */ @media (min-width: 1200px) { .t65 { color: red } } /*! lightningcss: (width<=1199.98px) */ @media (max-width: 1199.98px) { .t66 { color: red } } /*! webpack: a shorthand setting exactly two longhands merges like a box family */ .t70 { margin-block-start: 1px; margin-block-end: 2px } /*! ...collapsing to one value when both are equal */ .t71 { padding-inline-start: 1px; padding-inline-end: 1px } /*! ...and `gap`, whose longhands are named for the axes */ .t72 { row-gap: 1px; column-gap: 2px } /*! declined: two-value `overflow` is far newer than `overflow-x`/`-y`, so the merge would lose both declarations on a target that reads only the longhands */ .t73 { overflow-x: hidden; overflow-y: scroll } /*! webpack: ...but one-value `overflow` is CSS 2.1, as old as the longhands */ .t73a { overflow-x: hidden; overflow-y: hidden } /*! declined: `place-items` is newer than `align-items` in every form */ .t74 { align-items: center; justify-items: start } /*! declined: ...so an equal pair is no safer */ .t74a { align-items: center; justify-items: center } /*! declined: a declaration between them writing the same family would be stepped over by the merge */ .t75 { margin-block-start: 1px; margin: 0; margin-block-end: 2px } /*! declined: a CSS-wide keyword beside another value is a shorthand the engine drops whole, so the pair collapse refuses one exactly as a box does */ .t76 { margin-block-start: inherit; margin-block-end: 1px } .t76a { margin-block-start: inherit; margin-block-end: inherit } /*! declined: ...and a substitution could expand to both values at once */ .t77 { margin-block-start: var(--x); margin-block-end: var(--x) } /*! lightningcss: (1200px<=width<=2000px) — an `and` of two one-sided ranges on one feature is the interval it describes, whichever order they are written */ @media (min-width: 1200px) and (max-width: 2000px) { .t65a { color: red } } @media (max-width: 2000px) and (min-width: 1200px) { .t65b { color: red } } /*! declined: two comparisons the same way round are no interval */ @media (min-width: 1200px) and (min-width: 1300px) { .t65c { color: red } } /*! declined: `or` is not a conjunction */ @media (min-width: 1200px) or (max-width: 2000px) { .t65d { color: red } } /*! webpack: every range-type feature, and nested conditions */ @media (min-resolution: 2dppx) { .t67 { color: red } } @media ((min-width: 1px) and (max-height: 2px)) { .t68 { color: red } } /*! webpack: `@container` carries media features too, name and all */ @container card (min-width: 1px) { .t69 { color: red } } /*! declined: a plain feature has no range spelling to reach for */ @media (width: 100px) { .t70 { color: red } } /*! declined: a `@supports` condition is a declaration, not a media feature */ @supports (min-width: 1px) { .t71 { color: red } } /* Rounding and unit conversion, each verified against headless Chromium: the computed style of the authored form and of the emitted one are identical. */ /*! webpack: 6 significant digits is below what the engine reports */ .t72 { width: 33.33333333% } /*! webpack: ...and below the 1/64px it lays a length out in */ .t73 { width: 1.0000001px } /*! webpack: ...for a unitless number too */ .t74 { opacity: 0.123456789 } /*! webpack: declined: an angle is amplified by the trig in rotate() */ .t75 { transform: rotate(33.33333333deg) } /*! webpack: ...but a plain number argument rounds */ .t76 { transform: scale(1.123456789) } /*! webpack: declined: past 1e4 the rounded error would pass 1/64px */ .t77 { width: 33333.33333px } /*! webpack: the units CSS Values 4 fixes against each other convert */ .t78 { width: 16px } .t79 { width: 12pt } .t80 { width: 10mm } .t81 { transition-duration: 400ms } /*! webpack: ...only when the ratio divides exactly */ .t82 { width: 1.3px } /*! webpack: declined: `q` is a source only — Safari read it first in 15 */ .t83 { width: 10mm; height: 40q } /*! webpack: declined: a `@supports` condition tests the unit itself */ @supports (width: 16px) { .t84 { color: red } } /*! webpack: ...and the value it is tested with */ @supports (color: rgba(0, 0, 0, .5)) { .t85 { color: red } } /*! webpack: a media feature is evaluated, not tested, so it converts */ @media (min-width: 1200px) { .t86 { color: red } } /*! webpack: an alpha is the byte the engine already quantizes it to */ .t87 { color: rgba(0, 0, 0, .5) } .t88 { color: rgba(255, 0, 0, .2) } /*! webpack: ...collapsing to 4 digits when every pair repeats */ .t89 { color: rgba(255, 0, 0, .8) } /*! webpack: a custom property's value is respelled like any other */ .t90 { --width: 16px; --alpha: rgba(0, 0, 0, .5); --round: 33.33333333% } /* The polar and Lab color functions, each conversion read back from a canvas in headless Chromium: 11368 of them, none differing. */ /*! webpack: hwb() converts like hsl() */ .t91 { color: hwb(0 0% 100%) } /*! webpack: declined: a channel exactly on a `.5` boundary */ .t92 { color: hwb(194 0% 0%) } /*! webpack: lab(), lch(), oklab() and oklch() reach sRGB */ .t93 { color: lab(100% 0 0) } .t94 { color: lab(50% 40 59.5) } .t95 { color: lch(29.2345% 44.2 45deg) } .t96 { color: oklab(1 0 0) } .t97 { color: oklch(70% 0.1 200) } /*! webpack: ...with a percentage axis scaled to the space's own 100% */ .t98 { color: oklab(40.101% 0.1147% 0.0453%) } /*! webpack: declined: outside the sRGB gamut, a hex would clip it */ .t99 { color: oklch(90% 0.4 140) } /*! webpack: an alpha rides along into the hex */ .t100 { color: hsl(100 100% 50% / .8) } /* Four box longhands merge with unrelated declarations between them. */ /*! webpack: the merge steps over what does not write the family */ .t101 { margin-top: 1px; margin-right: 2px; color: red; margin-bottom: 1px; margin-left: 2px } /*! webpack: declined: the shorthand itself between them */ .t102 { margin-top: 1px; margin: 9px; margin-right: 2px; margin-bottom: 1px; margin-left: 2px } /*! webpack: declined: a logical property that writes the same sides */ .t103 { margin-top: 1px; margin-inline: 9px; margin-right: 2px; margin-bottom: 1px; margin-left: 2px } /*! webpack: declined: `all` writes everything */ .t104 { margin-top: 1px; all: unset; margin-right: 2px; margin-bottom: 1px; margin-left: 2px } /*! webpack: declined: `border` writes every border-color longhand */ .t105 { border-top-color: red; border: 1px solid; border-right-color: red; border-bottom-color: red; border-left-color: red } /*! webpack: ...but an unrelated property between them does not */ .t106 { border-top-color: red; color: red; border-right-color: red; border-bottom-color: red; border-left-color: red } /*! webpack: the four corners merge too, clockwise from the top left */ .t107 { border-top-left-radius: 1px; border-top-right-radius: 2px; border-bottom-right-radius: 3px; border-bottom-left-radius: 4px } /*! webpack: declined: a corner set to two radii needs the shorthand's `/` form */ .t108 { border-top-left-radius: 1px 2px; border-top-right-radius: 1px 2px; border-bottom-right-radius: 1px 2px; border-bottom-left-radius: 1px 2px } /*! webpack: declined: a logical corner writes the same corners */ .t109 { border-top-left-radius: 1px; border-start-start-radius: 9px; border-top-right-radius: 2px; border-bottom-right-radius: 3px; border-bottom-left-radius: 4px } /*! webpack: `corner-shape` lists its longhands by row, not clockwise */ .t110 { corner-top-left-shape: squircle; corner-top-right-shape: bevel; corner-bottom-right-shape: scoop; corner-bottom-left-shape: notch } /*! webpack: corrected to Chromium's pair, not `mdn-data`'s block-start one */ .t111 { corner-start-start-shape: bevel; corner-end-start-shape: notch } /*! webpack: ...the edge `mdn-data` mistook it for still merges as stated */ .t112 { corner-start-start-shape: bevel; corner-start-end-shape: notch } /*! webpack: two corner shorthands share a longhand, so only the first may claim it — the second landing on the first's blanked tail would drop that tail */ .t113 { corner-top-right-shape: notch; corner-top-left-shape: bevel; corner-bottom-left-shape: scoop } .t114 { corner-end-start-shape: scoop; corner-start-start-shape: bevel; corner-start-end-shape: notch } /* An order-free `||` shorthand merges when each value parses back to its slot. */ /*! webpack: a length, a style keyword and a color are each one slot's */ .t120 { outline-width: 3px; outline-style: dashed; outline-color: red } /*! webpack: ...a zero length keeps a slot of its own, and a color keyword too */ .t121 { outline-width: 0; outline-style: none; outline-color: currentcolor } /*! webpack: declined: `auto` is both an `outline-style` and an `outline-color` */ .t122 { outline-width: 3px; outline-style: auto; outline-color: auto } /*! webpack: declined: a substitution could stand for any of the three */ .t123 { outline-width: 3px; outline-style: dashed; outline-color: var(--c) } /*! webpack: declined: a CSS-wide keyword means something else in a shorthand */ .t124 { flex-direction: column; flex-wrap: inherit } /*! webpack: the merge steps over what does not write the family */ .t125 { column-rule-width: medium; color: red; column-rule-style: groove; column-rule-color: rebeccapurple } /*! webpack: declined: `outline-offset` is in the family and would be stepped over */ .t126 { outline-width: 3px; outline-offset: 1px; outline-style: dashed; outline-color: red } /*! webpack: four slots, and a percentage only the thickness takes */ .t127 { text-decoration-line: none; text-decoration-style: solid; text-decoration-color: #123; text-decoration-thickness: 10% } /*! webpack: a system color is a color keyword like any other */ .t128 { text-decoration-line: line-through; text-decoration-style: double; text-decoration-color: CanvasText; text-decoration-thickness: from-font } /*! webpack: two-slot families merge the same way */ .t129 { text-emphasis-style: sesame; text-emphasis-color: #abc } .t130 { flex-direction: row-reverse; flex-wrap: wrap-reverse } .t131 { text-wrap-mode: wrap; text-wrap-style: pretty } /*! webpack: only `text-emphasis-style` takes a string */ .t132 { text-emphasis-style: "x"; text-emphasis-color: red } /*! webpack: declined: a value no slot takes — the browser drops the declaration, and a merge must not rescue it into a shorthand it would read */ .t134 { flex-direction: 3px; flex-wrap: wrap } /*! webpack: declined: ...a unit no slot's type carries is not classified at all */ .t135 { outline-width: 2s; outline-style: dashed; outline-color: red } /*! webpack: declined: ...and only a zero number is a length without one */ .t136 { outline-width: 3; outline-style: dashed; outline-color: red } /*! webpack: declined: only 3, 4, 6 and 8 digits are a hex color, so merging a 5-digit hash would invalidate the shorthand and drop the width and style too */ .t137 { outline-width: 3px; outline-style: dashed; outline-color: #12345 } /*! webpack: declined: `list-style-type` takes any identifier, so no other value in the family is unambiguous — an image included */ .t133 { list-style-type: square; list-style-position: inside; list-style-image: url("data:image/gif;base64,R0lGODlhAQABAAAAACw=") } /*! webpack: a comment parts two components, so a rewrite keeps them apart */ .t138 { margin: 1px 1px/*c*/1px 1px } .t139 { transition: opacity/*c*/1s ease-in 2s } /*! webpack: a custom property's value stays as written, but a comment in it minifies to the boundary it stands for */ .t140 { --t140: 1px 1px/*c*/1px 1px } .t141 { --t141: 1px 1px/*!k*/1px 1px } .t142 { --t142: minmax(1px/*c*/2px, calc(3px/*c*/4px)) } /*! gradient: the last stop's position is where CSS Images 3's fix-up already puts it */ .t72 { background-image: linear-gradient(red, blue 100%) } /*! ...and a conic gradient's own turn, however it is spelled */ .t72b { background-image: conic-gradient(red, blue 360deg) } /*! gradient: two stops of one color are the one stop naming both positions */ .t72c { background-image: linear-gradient(red 0%, red 50%, blue) } /*! declined: a color hint is a position alone, so it is no stop to fold with */ .t72d { background-image: linear-gradient(red 0%, 30%, blue) } /*! declined: a stop already carrying two positions is not the one value to drop */ .t72e { background-image: linear-gradient(red 50% 100%, blue) } /*! declined: a prefixed gradient is a different function with its own grammar */ .t72f { background-image: -webkit-linear-gradient(red 0%, red 50%) } /*! a rotation about one axis is the call naming it (CSS Transforms 2 §13.1) */ .t73 { transform: rotateZ(37deg) } .t73a { transform: rotate3d(0, 0, 1, 37deg) } .t73b { transform: rotate3d(1, 0, 0, 37deg) } .t73c { transform: rotate3d(0, 1, 0, 37deg) } /*! declined: the engine normalizes the axis, so a negative one turns the angle */ .t73d { transform: rotate3d(0, 0, -1, 37deg) } /*! declined: a vector naming no axis is no single rotation */ .t73e { transform: rotate3d(1, 1, 0, 37deg) } /*! a size's omitted second value is `auto`, so writing it says nothing */ .t74 { background-size: 1rem auto } .t74a { background-size: 50% auto, 2px auto } /*! declined: the omitted value is `auto`, not the first repeated */ .t74b { background-size: 1rem 1rem } /*! declined: a substitution could make the `auto` a third value */ .t74c { background-size: var(--w) auto } /*! one reduction uncovers the next, down to the shortest call */ .t75 { transform: translate3d(-50%, 0, 0) } .t75a { transform: scale3d(1, 1, 1) } /*! declined: a z factor that scales keeps the 3D call */ .t75b { transform: scale3d(2, 3, 4) } /*! a skew along x is the pair whose second component is the 0 it means */ .t76 { transform: skewX(10deg) } /*! declined: a substitution could fill the second component */ .t76a { transform: skewX(var(--a)) } /*! an alpha percentage is the number a hundredth of it names */ .t77 { opacity: 100% } .t77a { opacity: 33.33% } .t77b { shape-image-threshold: 12.5% } /*! declined: the number is no shorter than the percentage */ .t77c { opacity: 5% } /*! a ratio's denominator of 1 is the one an omitted denominator means */ .t78 { aspect-ratio: 2 / 1 } .t78a { aspect-ratio: auto 3/1 } /*! declined: another denominator is another ratio */ .t78b { aspect-ratio: 2/10 } /*! webpack: a 3D matrix whose third row and column are the identity's is 2D */ .t95 { transform: matrix3d(20, 20, 0, 0, 40, 40, 0, 0, 0, 0, 1, 0, 80, 80, 0, 1) } /*! declined: ...but only then */ .t96 { transform: matrix3d(20, 20, 0, 0, 40, 40, 0, 0, 0, 0, 1, 5, 80, 80, 0, 1) } /*! webpack: a 2D pair of 1 leaves the z scale alone */ .t97 { transform: scale3d(1, 1, 1.5) } /*! webpack: a zero time keeps a unit, and `s` is the shorter one it can carry */ .t98 { transition-duration: 0ms } /*! webpack: a component spelling the property's own initial says nothing beside another — omitting its group leaves exactly that keyword */ .t99 { grid-auto-flow: row dense } /*! declined: the other alternative of the group is not the initial */ .t99a { grid-auto-flow: column dense }