8 March, 20223 minute read

RIP CSS `color-mod` function

Something about applying colors in CSS feels awkward and out of place. While font sizes can be determined on-the-fly from a modular scale, and margins and paddings can be calculated off a vertical rhythm. Colors, on the other hand, are a different story.

CSS has no ability to manipulate colors unless you do some funky things with CSS variables. This is a frustrating limitation because every user interface needs to derive "stateful" colors from some base color at some point. Hovering a button, for instance, might slightly lighten the button's color while clicking the button might darken its color. There's no perfect solution for this problem, and everything has tradeoffs.

The simplest approach is to simply hardcode all of your derived colors into your CSS bundle. While this works, it's clearly not a great solution because it isn't very DRY and any change of palette will require time spent tracking down and changing all of the derived colors. CSS variables help out a lot here—at least you can define the values in one place—but it's still far from ideal.

CSS preprocessors like SASS offer comprehensive color manipulation functions, but this approach is limiting from a technical standpoint. It required you to be using something like CSS modules for styling, and it hopeless in any situation where the color you're manipulating is dynamic. An easy example of this in action is an app like Google Classroom where users are able to choose a unique color for each of their "classrooms." The UI rethemes itself based on the classroom's color, and so unless you limit users to only a handful of color options you cannot implement this retheming using only a preprocessor. After all, preprocessors work by calculating the final color at build time and inlining that result into the CSS bundle.

These days, CSS-in-JS solutions like styled-components or jss are popular. In cases like this the problem solves itself: npm add whatever color library you prefer, and then you're away laughing. This is the closest solution to a good one, but a). some of these libraries are huge; and b). you might wind up including multiple equivalent libraries transitively via dependencies of your app. Bundle size is a big deal, so this just isn't a realistic solution for the web longterm. The 15kB color2 library is between 8.8-11.5% of your overall performance budget—just to calculate some theme colors! We need a better solution.

That better solution would have been the CSS color-mod function. color-mod would have offered almost all of the manipulations available in Javascript libraries without requiring any additional bundle size1. Even better, because it was supposed to be a standard feature of CSS everyone would be familiar with the syntax and wouldn't need to contend with subtly different color libraries (e.g. is darken from 0 to 1, or from 0 to 100?)

Unfortunately, color-mod was removed from the CSS Color Module Level 4 Working Draft back in 2016 due to concerns around its syntax and a desire to base color manipulations on the LAB color space instead of RGB. These are reasonable concerns: there are enough examples of awkward web standards without adding another one, and while Javascript color manipulators tend to work on RGB we should want the "standard" way of manipulating colors to work on the best color space available. Migrating color-mod from RGB to LAB at some point down the line would have been a challenging undertaking.

Since the removal of color-mod, it seems like interest in this CSS feature has died out somewhat. I don't see many people talking about it today and I think that's a shame. It would have made our web apps smaller and improved developer experience around a widespread UI challenge.

Hopefully someone will champion this feature again soon :)

  1. Ignoring the potential need to polyfill, of course.

Don't want to miss out on new posts?

Join 100+ fellow engineers who subscribe for software insights, technical deep-dives, and valuable advice.

Get in touch 👋

If you're working on an innovative web or AI software product, then I'd love to hear about it. If we both see value in working together, we can move forward. And if not—we both had a nice chat and have a new connection.
Send me an email at hello@sophiabits.com