Build a custom palette using color-mix() in TailwindCSS
In this post, we will see how to use CSS function color-mix()
with CSS variables to generate a custom palette for our Nuxt application efficiently with TailwindCSS.
Table of Content
- Table of Content
- Prerequisites
- Understanding color palette variants
- Generate the palette with tint and shade variants with color-mix()
- Using color-mix() with currentColor and CSS variables
- Browser support
- Resources
- Summary
Prerequisites
It would be best if you had your Nuxt application set up by using the following command:
npx nuxi init tailwindcss-color-mix
Selecting TailwindCSS as a dependency during the installation prompts would be best.
Once created, within the project's root directory, you should create two files - one is tailwind.css
located in the styles
folder with the following code:
/** styles/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
And we create another file, tailwind.config.js
, for extending the configuration of TaiwindCSS in the project:
/** tailwind.config.js */
module.exports = {
}
Then in nuxt.config.js
, you need to set the tailwindcss
plugin's configuration with the following code:
/** nuxt.config.js */
export default {
//...
tailwindcss: {
cssPath: '~/styles/tailwind.css',
configPath: '~/tailwind.config.js'
},
}
And we are ready for our tutorial!
Understanding color palette variants
A TailwindCSS color palette is a set of colors divided into two sections: the lighter colors (tint variants) and the darker colors (shade variants). The tint variants are in the scope of 50 to 400, and the darker colors are from 600 to 900, with the base color as a variant of 500. An example of the TailwindCSS palette for color #96454c
is as below:
There are many ways to generate color palette variants. You can use Color Palette Generator to build a palette from an image or build your mechanism to take a color and generate the appropriate palette using JavaScript.
Or you can use the CSS function - color-mix()
to achieve this goal.
Generate the palette with tint and shade variants with color-mix()
color-mix()
is a CSS function that accepts two colors and returns the desired mixed color variant based on a given color space. To use color-mix()
, we will need to define the colorSpace
for calculating the value of mixing the baseColor
and the blendingColor
, as in the following syntax:
color-mix(
in colorSpace,
baseColor <baseColorPercent>,
blendingColor <blendingColorPercent>
)
We can also indicate the baseColorPercent
percentage of the baseColor
and blendingColorPercent
of blendingColor
the browser should use for mixing, when applicable. Below is an example of mixing 50%
red color with 20%
white color in sRGB
color space with color-mix()
:
While the baseColor
and blendingColor
can be any CSS-supported color values, we can also use color-mix()
for different color spaces for color mixing, from sRGB to HSL. The result color will vary per chosen color space. For this post, we will use sRGB as our color space.
Now we understand how color-mix()
works, we will explore how we generate the tint and share variants for our Tailwind color palette.
Generating tint variants
As mentioned, the tint variants are lighter shades of a base color, resulting from blending a base color with white at a certain intensity level (or percentage).
In other words, we create a new variant by mixing a color with a percentage of white, using color-mix()
with the following formula:
color-mix(in srgb, <color>, white <whitePercentage>)
Based on the above formula, we implement a function getTintVariantColor
which accepts a base color
and an intensity
value from 0 to 1 and returns a string containing the appropriate CSS code with color-mix
:
function getTintVariantColor(color, intensity) {
return `color-mix(in srgb, ${color}, white ${intensity * 100}%)`
}
And since we need the variants of 50, 100, 200, and 400 for our tints, we can gradually increase the values whitePercentage
for each variant level accordingly, as in the following example:
const tintVariants = {
50: 0.95, //95%
100: 0.9, //90%
200: 0.7, //70%
300: 0.5, //50%
400: 0.3, //30%
}
Great. Now let's head to the tailwind.config.js
file and provide our custom palette from the primary color #96454c
, using the theme.extend.colors
field in the tailwind.config.js
file, as follows:
module.exports = {
theme: {
extend: {
colors: {
primary: {
50: getTintVariantColor('#96454c', tintVariants.50),
100: getTintVariantColor('#96454c', tintVariants.100),
200: getTintVariantColor('#96454c', tintVariants.200),
300: getTintVariantColor('#96454c', tintVariants.300),
400: getTintVariantColor('#96454c', tintVariants.400),
500: '#96454c',
}
},
}
},
}
That's it. When you add the following code to the pages/index.vue
file, you will see the tint color palette for the primary color #96454c
:
<template>
<main class="flex items-center flex-col gap-5 my-10">
<h1>Current template:</h1>
<h2 class="text-primary-500">Base color: #96454c</h2>
<ul style="width: 200px">
<li
v-for="variant in palettes"
:class="`bg-primary-${variant} px-3 py-2 ${ variant > 500 ? 'text-white': ''}`"
key="variant"
>
{{variant}}
</li>
</ul>
</main>
</template>
<script setup>
const palettes = [50, 100, 200, 300, 400, 500]
</script>
Since we are dynamically computing the classes in the template, we need to add primary
color's class pattern to the safelist
of TailwindCSS configuration. Otherwise, TailwindCSS will not generate the relevant classes since it thinks they are unused.
module.exports = {
//...
safelist: [
{
pattern: /\-primary\-/,
}
]
}
Alternatively, we can also define the percentage of our base color instead of white for our color mixer. In this case, we calculate the colorPercentage
value as 100% - whitePercentage
for each intensity level:
const tintVariantsForBaseColor = {
50: 0.05, //95% white
100: 0.1, //90%
200: 0.3, //70%
300: 0.5, //50%
400: 0.7, //30%
}
And our formula will change to the following:
color-mix(in srgb, <color> <colorPercentage>%, white)
The result should remain the same as the previous implementation.
Next, we will apply the same approach to generate the shade variants.
Generating shade variants
While the tints are the variants that resulted from mixing a color with white, as darker variants, shades are the colors that resulted from mixing our target color with black at some intensity level. Following the previous formula for the tint colors, we can write a function getShadeVariantColor()
in a similar way:
function getShadeVariantColor(color, intensity) {
return `color-mix(in srgb, ${color}, black ${intensity * 100}% )
}
And we also need to define the intensity level, on a scale of 0 to 1, as the variants of 600, 700, 800, and 900 for our shades, by gradually increasing its value by 0.2 (20%):
const tintVariants = {
600: 0.1, //10%
700: 0.3, //30%
800: 0.5, //50%
900: 0.7, //70%
}
Then in tailwind.config.js
, we will use the getShadeVariantColor()
function to generate the remaining variants for our primary color:
module.exports = {
theme: {
extend: {
colors: {
primary: {
//...
600: getShadeVariantColor('#96454c', shadeVariants.600),
700: getShadeVariantColor('#96454c', shadeVariants.700),
800: getShadeVariantColor('#96454c', shadeVariants.800),
900: getShadeVariantColor('#96454c', shadeVariants.900),
}
},
}
},
}
And in the pages/index.vue
file, we can add the remaining variant codes to palettes
as follows:
<script setup>
const palettes = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]
</script>
We will now see the whole palette displayed in the browser:
Great. But what if we want to change the primary base color to another? Manually replacing each row of the variant's calculation can be inefficient. We need to find a way to make it more dynamic, such as using the help or currentColor
or CSS variables. Let's explore it next.
Using color-mix() with currentColor and CSS variables
Unfortunately, we can't use currentColor
inside color-mix()
. However, we can use CSS variables with the help of the var()
function and color-mix()
.
Take our example color palette, for instance. Instead of mapping the color code directly in the configuration file, we can assign a CSS variable --color-primary-base
to the extensive base layer in our tailwind.css
file, as follows:
/**styles/tailwind.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--color-primary-base: #96454c;
}
}
Then in tailwind.config.js
, we will change the value of #96454c
to var(--color-primary-base)
:
colors: {
'primary': {
50: 'color-mix(in srgb, var(--color-primary-base) 5%, white)',
100: 'color-mix(in srgb, var(--color-primary-base) 10%, white)',
200: 'color-mix(in srgb, var(--color-primary-base) 30%, white)',
300: 'color-mix(in srgb, var(--color-primary-base) 50%, white)',
400: 'color-mix(in srgb, var(--color-primary-base) 70%, white)',
500: 'var(--color-primary-base)',
600: 'color-mix(in srgb, var(--color-primary-base), black 10%)',
700: 'color-mix(in srgb, var(--color-primary-base), black 30%)',
800: 'color-mix(in srgb, var(--color-primary-base), black 50%)',
900: 'color-mix(in srgb, var(--color-primary-base), black 70%)',
},
},
The result stays the same, but whenever we want to change the primary base color, we only need to change the value of --color-primary-base
in the main CSS file.
Browser support
At the point of writing, most browsers support this feature except Firefox version 88 and above. Hence, consider implementing a fallback if Firefox is required.
Resources
Summary
In this tutorial, we have briefly learned how to build a variant palette for color using CSS functions color-mix()
, var()
, CSS variables, and JavaScript in a TailwindCSS-Nuxt-powered application. Indeed, you can use the same approach to calculate the color themes for any web application development, not limited to Nuxt and TailwindCSS.
While color-mix()
can be helpful in pure CSS in many cases, it may not be the optimal choice due to the browser limitation (Firefox). In such scenarios, using the built-in functionality of TailwindCSS for theming or an external tool like Color Palette Generator may be a better solution. Nevertheless, the power of pure CSS is getting more robust with more handy features, which is worth waiting for!
If you have tried CSS functions like color-mix()
or any other, share your experience with me in the comment section!
๐ If you'd like to catch up with me sometimes, follow me on Twitter | Facebook.
๐ Learn about Vue with my new book Learning Vue. The early release is available now!
Like this post or find it helpful? Share it ๐๐ผ ๐