demo · v140
Cross-Type Grid
Which combinations of types does calc() let you mix? Length over length yields a number. Number times length yields a length. Two angles divided produce a number; one angle plus one length is still an error. The full matrix in one table.
| length | angle | percentage | time | number | |
|---|---|---|---|---|---|
| length | L + L → length | L + A | L + L% → length | L + T | L × N → length |
| length (÷) | L / L → number (new) | L / A | L / L% → number | L / T | L / N → length |
| angle | A + L | A + A → angle | A + % | A + T | A × N → angle |
| angle (÷) | A / L | A / A → number (new) | A / % | A / T | A / N → angle |
| time | T + L | T + A | T + % | T + T → time | T × N → time |
| time (÷) | T / L | T / A | T / % | T / T → number (new) | T / N → time |
The big shift in 140 is X / X → number: same-type division finally produces a unitless value that can flow into opacity, flex-grow, animation iteration counts, anything that wants a plain number.
/* All of these previously needed a tan(atan2(...)) hack. */
.bar { width: calc(100% * (var(--w) / 100px)); }
.spinner { opacity: calc(var(--angle) / 1turn); }
.delay-as-frac { z-index: calc(var(--delay) / 1s * 60); }
why N matters
A unitless number can be used as: a multiplier for any unit, an iteration count, an opacity, a flex factor, a Z-index, a grid track count. Once the engine can produce a number from typed inputs, every property that takes a number becomes addressable from a single typed custom property. That's what unlocks scroll-driven animation, container-query-driven typography, and the rest of the calc() story.
see also
- CSS typed arithmetic — feature index
- ChromeStatus entry
- Type checking rules
scenario focus
Select a scenario to focus its rendered example and summary.