Build a custom palette using color-mix() in TailwindCSS
Tags: tailwindcss, nuxt, css, tutorials
Published: 2023-04-19 04:03:34

---
title: "Build a custom palette using color-mix() in TailwindCSS"
description: "How to generate color palette using CSS color-mix() function and for your TailwindCSS application"
cover_image: https://res.cloudinary.com/mayashavin/image/upload/v1681848724/articles/CSS/color_mix_banner.png
published: true
canonical_url: https://mayashavin.com/articles/build-palette-color-mix-css-tailwindcss
series: Efficient CSS
tags: ['TailwindCSS', 'Nuxt', 'CSS', 'tutorials']
---

_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](#table-of-content)
- [Prerequisites](#prerequisites)
- [Understanding color palette variants](#understanding-color-palette-variants)
- [Generate the palette with tint and shade variants with color-mix()](#generate-the-palette-with-tint-and-shade-variants-with-color-mix)
  - [Generating tint variants](#generating-tint-variants)
  - [Generating shade variants](#generating-shade-variants)
- [Using color-mix() with currentColor and CSS variables](#using-color-mix-with-currentcolor-and-css-variables)
- [Browser support](#browser-support)
- [Resources](#resources)
- [Summary](#summary)

## Prerequisites

It would be best if you had your Nuxt application set up by using the following command:

```bash
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:

```css
/** 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:

```javascript
/** tailwind.config.js */
module.exports = {
}
```

Then in `nuxt.config.js`, you need to set the `tailwindcss` plugin's configuration with the following code:

```javascript
/** 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:

<img src="https://res.cloudinary.com/mayashavin/image/upload/f_auto,q_auto/v1675680195/articles/CSS/rust_palette" loading="lazy" alt="Color variants for Copper Rust color" class="mx-auto"/>

There are many ways to generate color palette variants. You can use [Color Palette Generator](https://colorgen.dev/) 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:

```js
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()`:

<img src="https://res.cloudinary.com/mayashavin/image/upload/f_auto,q_auto/v1675680195/articles/CSS/tint_formula" loading="lazy" alt="Mixed color generated in CSS" class="mx-auto"/>

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](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix). 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:

```js
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`:

```js
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:

```js
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:

```javascript
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`:

```html
<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>
```

<img src="https://res.cloudinary.com/mayashavin/image/upload/f_auto,q_auto/v1675680195/articles/CSS/tint_variants2" loading="lazy" alt="Tint variants" class="mx-auto"/>

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.

```js
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:

```js
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:

```js
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%):

```js
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:

```javascript
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:

```html
<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:

<img src="https://res.cloudinary.com/mayashavin/image/upload/f_auto,q_auto/v1675680195/articles/CSS/full_variants" loading="lazy" alt="Color variants for #96454c" class="mx-auto"/>

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:

```css
/**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)`:

```javascript
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

* [MDN - color-mix()](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix)
* [Simplify Your Color Palette With CSS Color-Mix()](https://www.smashingmagazine.com/2022/06/simplify-color-palette-css-color-mix/)
* [color-mix() - Color Module 5](https://www.w3.org/TR/css-color-5/#color-mix)

## 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](https://colorgen.dev/) 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](https://twitter.com/MayaShavin) | [Facebook](https://www.facebook.com/mayashavin/)._

👉 _Learn about Vue with my new book [Learning Vue](https://www.oreilly.com/library/view/learning-vue/9781492098812/). The early release is available now!_

Like this post or find it helpful? Share it 👇🏼 😉