CSS Custom Properties Can Now Curry — No calc() Required
While poking around the Utopia website, a responsive typography project, I spotted CSS that looked wrong at first: math operators in custom properties with no calc() wrapper. Turns out that's intentional — and it's a clever technique Trys Mudford, one of Utopia's creators, explains on his blog.
:root {
--fluid-max-negative: (1 / var(--fluid-max-ratio) / var(--fluid-max-ratio));
--fluid-min-negative: (1 / var(--fluid-min-ratio) / var(--fluid-min-ratio));
...
}
The key insight, per Mudford:
The value after the
:in the CSS custom property does not have to be valid CSS. It won’t cause any errors, nor invalidate the custom property. It won’t be evaluated in the browser until used, or more specifically, placed in acalc()function.
:root {
--padding: 1rem;
/* These are meaningless alone */
--padding-S: var(--padding) / 2;
--padding-L: var(--padding) * 2;
}
.module--large {
/* But they evaluate once they are in a calc() */
padding: calc(var(--padding-L));
}
In functional programming, currying means functions that return other functions. This feels analogous: the extra padding properties behave like derived variants of a base "function," only evaluated when you actually invoke them via calc() — deferring computation until the browser needs it.



