Below is an excerpt of css being implemented in a WordPress mechanism to generate css-only Low Quality Image Placeholders (https://github.com/WordPress/performance/pull/2550/changes), inspired by this article https://leanrada.com/notes/css-only-lqip/
@property --lqip {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
[style*="--lqip:"] {
--lqip-ca: mod(round(down, calc((var(--lqip) + 524288) / 262144)), 4);
--lqip-cb: mod(round(down, calc((var(--lqip) + 524288) / 65536)), 4);
--lqip-cc: mod(round(down, calc((var(--lqip) + 524288) / 16384)), 4);
--lqip-cd: mod(round(down, calc((var(--lqip) + 524288) / 4096)), 4);
--lqip-ce: mod(round(down, calc((var(--lqip) + 524288) / 1024)), 4);
--lqip-cf: mod(round(down, calc((var(--lqip) + 524288) / 256)), 4);
--lqip-ll: mod(round(down, calc((var(--lqip) + 524288) / 64)), 4);
--lqip-aaa: mod(round(down, calc((var(--lqip) + 524288) / 8)), 8);
}
W3C CSS Validator shows these errors
1 Unrecognized at-rule @property
8 [style*="--lqip:"] The types are incompatible ), 4)
9 [style*="--lqip:"] The types are incompatible ), 4)
10 [style*="--lqip:"] The types are incompatible ), 4)
11 [style*="--lqip:"] The types are incompatible ), 4)
12 [style*="--lqip:"] The types are incompatible ), 4)
13 [style*="--lqip:"] The types are incompatible ), 4)
14 [style*="--lqip:"] The types are incompatible ), 4)
15 [style*="--lqip:"] The types are incompatible ), 8)
15 [style*="--lqip:"] Parse Error
As noted in a code review comment there, this is what Claude Opus 5 said
Both tools are wrong, and about the same thing: the two‑argument round(down, A) form where the rounding interval B is omitted.
What the spec says
css-values-4 §10.3:
The round(<rounding-strategy>?, A, B?) function … If the type of A matches <number>, then B may be omitted, and defaults to 1. … In all other cases, omitting B is invalid.
--lqip is registered as syntax: "<number>" (lqip.css:12-16), so A is a <number> and omitting B is legal. The code is correct.
Why the error points at mod() instead of round()
Neither tool can establish a type for the round() result, so it falls through to mod()'s "both arguments must be the same type" check against the literal 4/8. That's also why lqip.css:27 — mod(calc(var(--lqip) + 524288), 8), no round() — is clean in both tools while lines 19‑26 are not.
The two tools fail for different reasons
I probed both with variants:
| Expression |
PhpStorm |
W3C |
round(down, 5) |
ok |
error |
round(down, var(--lqip)) |
ok |
— |
round(down, calc(var(--lqip) + 1)) |
error |
error |
round(down, …, 1) (explicit interval) |
ok |
ok |
- PhpStorm does implement the number default — it even reads your
@property to type a bare var(--lqip). It just loses the type when the argument is a calc() containing a var(). Dropping the redundant calc() wrapper (round(down, (var(--lqip) + 524288) / 262144)) doesn't help.
- W3C/Jigsaw doesn't implement the omitted-
B rule at all — even round(down, 5) reports "The types are incompatible."
Browsers disagree with both
In Chrome 152, with --lqip: 192900, the omitted-interval and explicit-interval forms both compute --lqip-ca: 2, and CSS.supports('opacity', 'round(down, 0.5)') is true.
If you want the warnings gone
Adding the explicit , 1 to the eight round() calls is a semantic no-op that satisfies both tools. Verified on a copy: W3C goes from 9 errors to 1, PhpStorm to 0.
--lqip-ca: mod(round(down, calc((var(--lqip) + 524288) / 262144), 1), 4);
The remaining W3C error is Unrecognized at-rule "@property" at lqip.css:12 — a separate Jigsaw gap (it predates css-properties-values-api), and nothing you can or should work around.
So, there's two issues:
- not recognizing the calc as number
- Not recognizing @Property
This resolves the calc/round error, but shouldn't be necessary (and isn't, in actual browsers)
--lqip-ca: mod(round(down, calc((var(--lqip) + 524288) / 262144), 1), 4);
--lqip-cb: mod(round(down, calc((var(--lqip) + 524288) / 65536), 1), 4);
--lqip-cc: mod(round(down, calc((var(--lqip) + 524288) / 16384), 1), 4);
--lqip-cd: mod(round(down, calc((var(--lqip) + 524288) / 4096), 1), 4);
--lqip-ce: mod(round(down, calc((var(--lqip) + 524288) / 1024), 1), 4);
--lqip-cf: mod(round(down, calc((var(--lqip) + 524288) / 256), 1), 4);
--lqip-ll: mod(round(down, calc((var(--lqip) + 524288) / 64), 1), 4);
--lqip-aaa: mod(round(down, calc((var(--lqip) + 524288) / 8), 1), 8);
Below is an excerpt of css being implemented in a WordPress mechanism to generate css-only Low Quality Image Placeholders (https://github.com/WordPress/performance/pull/2550/changes), inspired by this article https://leanrada.com/notes/css-only-lqip/
W3C CSS Validator shows these errors
As noted in a code review comment there, this is what Claude Opus 5 said
So, there's two issues:
This resolves the calc/round error, but shouldn't be necessary (and isn't, in actual browsers)