Quick and Dirty Colour Palettes using color-mix()
On This Page:
When I first started tinkering on the idea of a redesign of this site in ~2019 (yeah, it took that long) I started prototyping the layout (which changed) and other aspects of the site (theming) using CodePen.
To make things easier with my idea for theming (having lighter and darker variations of the primary colour for the background, foreground, etc.) I looked at using the (then) relatively new CSS feature color-mix()
.
What is color-mix()?
Simply put, rhe color-mix()
CSS function lets you blend two colours together. You also have the option to choose how much of each colour you want to mix and pick the colour space it works in, like srgb
, or display-p3
.
This makes it great for creating simple colour palettes with:
- tints: adding a bit of white to lighten a colour.
- shades: mixing in black to darken it.
- opacity: blend a colour with the
transparent
keyword to allow the background to bleed through.
The syntax for color-mix
is quite simple:
Here's what each part means:
<color-space>
specifies the colours space to do the blending in, common options are:srgb
anddisplay-p3
.<color-1>
is the first colour in the mix, this could be a custom property. a named colour, or a colour code.<percentage-1>
denotes the proportion of the first colour to be blended.<color-2>
is the second colour that is to be blended.<percentage-2>
would be how much of the second colour is mixed with the first.
You can also omit one of the percentages, the remaining percentage is automatically calculated:
Can be shortened to either:
Or:
Adam explains how color-mix()
works and more in this Chrome Developers blogpost.
Creating Simple Colour Palettes
Let's start with a primary colour and black and white as CSS custom properties and generate some tints and shades using color-mix()
.
With just a few lines, you’ve got lighter and darker variations that you can reuse for things like hover states, text, or borders.
Adding Opacity Variants
If you need semi-transparent colours, color-mix()
works just as well. By blending with transparent
, you can create a range of opacity levels:
These could be super handy for things like overlays, highlights, or subtle backgrounds.
Building A Colourful Neutral Palette
Your neutral colours, going from white to black could look a little better if they had some of your primary colour in the mix. Using color-mix()
makes this super easy:
This can give your neutral colour palette a softer tone that feels connected to the primary colour.
If you define a percentage for both colours, but that percentage does not add up to 100% the remaining percentage of the colour is transparent
.
Bringing It Together
So far, we've looked at creating simple tint, shade, opaque, and neutral colour palettes using the color-mix()
function. Below is a demo of these colour palettes, include options to:
- change the primary colour
- set the percentage of colour to add to the neutral palette
- the CSS of the palettes that can be copied and pasted into your codebase.
Creating a 'Dirty Hack' Dynamic color-mix()
For even quicker prototyping you can create a 'dynamic' custom property that uses the *
selector.
What’s Happening Here?
--custom-color
: Allows you to set a custom colour, which falls back to the--primary-color
;--mix-color
: Sets a new colour to mix which defaults to--color-white
;--mix-value
: Controls the percentage of the mix dynamically.*
: Declares the calculated--color
and makes it available to all elements
Performance Issues with the * Selector
While the *
selector is useful for experimentation, it’s not suitable for production due to potential performance concerns:
- Recalculation Costs: Every element on the page could recalculate the --color property whenever --value changes.
- Specificity Conflicts: The
*
selector applies styles indiscriminately, potentially overriding intended styles.
The Future with CSS Functions
Looking ahead, Functions and Mixins in CSS aim to replace common preprocessing patterns by giving CSS authors the ability to define reusable logic natively.
These functions operate in the value space of CSS, meaning they compute and return values like colours, lengths, or strings, which can then be assigned to properties.
Combining the CSS color-mix()
feature with the proposed custom function syntax could create a better way for dynamic
This CSS function takes two colours and a percentage and then returns the computed mixed colour for use anywhere it is called in the CSS.
Benefits and Concerns with Native CSS Functions and Mixins
Native CSS functions and mixins bring some exciting possibilities. They let you skip preprocessors like Sass or PostCSS, which can simplify your workflow by reducing dependencies and build steps.
That said, they’re not without challenges. Performance might take a hit with complex functions that need constant recalculations, like during animations. Planning reusable functions and mixins also requires thought, especially when juggling things like fallbacks or cascading rules.
The W3C is currently exploring this new specification to enhance CSS’s flexibility. As this specification is still under discussion, its details may evolve, it may be some time before we can experiment and use it in production. It's exciting, none-the-less.
Using Sass to Automate CSS Custom Properties
Whilst we're waiting for the cool new CSS with functions and mixins, and if you're already using Sass in your code base we can make things a little easier by using Sass mixins to generate the custom properties - nobody's got time to write (almost) the same code out 10, 20, 30, 40 times.
Here's a little Sass mixin that will generate the CSS custom properties for tint, shade, opaque, and neutral colour palettes
We will use a @for
loop to help us, in this example we're only creating a tint colour palette of CSS custom properties:
To make use of the Sass mixin in our code we would need to @include
it also:
This would generate a set of CSS custom properties:
The Sass Mixin in Full
Here is the complete Sass mixin that would generate the four colour palettes as CSS custom properties using color-mix()
:
I hope I have showed you how simple it can be to quickly create your own colour palettes with color-mix()
. Whether you're prototyping or advancing the colour system within your Design System, I think this is a great CSS feature to add to your CSS toolkit.