From e38fe96acec5d4667df84985b9a943bf973f41d5 Mon Sep 17 00:00:00 2001 From: Sarath Francis Date: Wed, 22 Jul 2026 03:38:11 -0400 Subject: [PATCH] Keep zero-length units inside all CSS math functions The zero-length unit optimization guards against calc(), min(), max() and clamp(), but strips the unit inside the other CSS math functions. For example round(0px, 3px) is rewritten to round(0, 3px). Inside a math function a unitless zero is a , not a zero , so the two arguments no longer share a type and the value becomes invalid, dropping the declaration. Add the remaining math functions (round, mod, rem, the trigonometric, exponential and sign-related functions) to the set so their zero-length arguments keep their unit. --- fixtures/compress/units/5.css | 22 +++++++++++++++++++++ fixtures/compress/units/5.min.css | 1 + lib/replace/Dimension.js | 32 +++++++++++++++++++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 fixtures/compress/units/5.css create mode 100644 fixtures/compress/units/5.min.css diff --git a/fixtures/compress/units/5.css b/fixtures/compress/units/5.css new file mode 100644 index 00000000..fce7f55c --- /dev/null +++ b/fixtures/compress/units/5.css @@ -0,0 +1,22 @@ +/* + issue #426 added min()/max()/clamp() to the math functions where a zero value + keeps its unit. The same rule applies to the other CSS math functions: inside + round(), mod(), rem(), hypot(), abs() etc. a unitless zero is a , not a + zero , so dropping the unit turns a valid value into an invalid one. +*/ + +.round { + width: round(0px, 3px); + height: round(nearest, 0px, 3px); +} +.mod-rem { + width: mod(0px, 3px); + height: rem(0px, 3px); +} +.hypot-abs { + width: hypot(0px, 3px); + height: abs(0px); +} +.nested { + width: calc(1px + round(0px, 3px)); +} diff --git a/fixtures/compress/units/5.min.css b/fixtures/compress/units/5.min.css new file mode 100644 index 00000000..b79de7e9 --- /dev/null +++ b/fixtures/compress/units/5.min.css @@ -0,0 +1 @@ +.round{width:round(0px,3px);height:round(nearest,0px,3px)}.mod-rem{width:mod(0px,3px);height:rem(0px,3px)}.hypot-abs{width:hypot(0px,3px);height:abs(0px)}.nested{width:calc(1px + round(0px,3px))} \ No newline at end of file diff --git a/lib/replace/Dimension.js b/lib/replace/Dimension.js index edb00388..008aa78f 100644 --- a/lib/replace/Dimension.js +++ b/lib/replace/Dimension.js @@ -2,9 +2,36 @@ import { packNumber } from './Number.js'; const MATH_FUNCTIONS = new Set([ 'calc', + + // comparison functions 'min', 'max', - 'clamp' + 'clamp', + + // stepped value functions + 'round', + 'mod', + 'rem', + + // trigonometric functions + 'sin', + 'cos', + 'tan', + 'asin', + 'acos', + 'atan', + 'atan2', + + // exponential functions + 'pow', + 'sqrt', + 'hypot', + 'log', + 'exp', + + // sign-related functions + 'abs', + 'sign' ]); const LENGTH_UNIT = new Set([ // absolute length units @@ -49,7 +76,8 @@ export default function compressDimension(node, item) { return; } - // issue #222: don't remove units inside calc + // issue #222: don't remove units inside a math function (calc(), round(), etc.), + // where a unitless zero is a rather than a zero if (this.function && MATH_FUNCTIONS.has(this.function.name)) { return; }