Interpolating between themes in CSS

color-mix(), var(), calc(), pow(), min()… some pretty cool possibilities arise.

Draft: started Tagged /css, /meta=also

Another thing that came up while I

After writing most of A few ways of specifying per-theme colours in CSS, I found I wanted to play with the color-mix(…, … var(--dark)) technique, to experiment with interpolating.

Here are some results of

Why stick with only “light mode” and “dark mode”?

Various forms of easing interpolation
Linear interpolation
Sine
Quadratic in
Quadratic out
Quadratic
Cubic
Quartic
Quadratic light, quartic dark
Quartic light, linear dark
Linear light, quadratic out dark
For quadratic easing, we need a piecewise function. From 0 to 0.5: pow(var(--v)*2,2)/2. From 0.5 to 1: 1 - pow(var(--v)*2 - 2,2)/2. A few solutions for achieving a piecewise function: calc(min(pow(var(--v)*2,2)/2,.5)-max(.5-pow(var(--v)*2 - 2,2)/2,0)) How do we do the “only from 0.5 to 1” thing? There are a few ways; I think the easiest uses sign(), but that only landed in the Chromium family in mid-2025. So instead, I’ll do a more convoluted thing with abs() and pow(). The easiest way is to use max(). abs(). x - abs(x - 0.5) Subtract 0.5, max( ((var(--v) - 0.5)*2)²
Body text: Fonts:
Theme:
Explanation of all this
(yes, this works without JavaScript; persists to cookies)