A deep dive into the CSS color-mix() function and future of colors on the web.
Tags: webdev, css, programming, html
Published: 2023-04-01 16:54:56

I have always been fascinated by the power of colors in shaping the visual appeal of websites even tho I always considered a very hard problem to tacle scientifically. With the upcoming CSS `color-mix()` function, I am excited to share my insights and experiments with this groundbreaking feature that is set to change the way we work with colors in our projects and especially design systems.

In this detailed and personal exploration, I will discuss the `color-mix()` function from my perspective, delving into various color spaces, such as HSL, RGB, LCH, and sRGB, and providing in-depth examples to showcase the versatility and potential of this innovative addition to the CSS specification. Furthermore, we will explore the benefits of incorporating the `color-mix()` function into design systems with tokens, along with examples showcasing how to work with colors and their alpha values, as well as using CSS custom properties on the `:root` element.

## The Science Behind the CSS `color-mix()` Function

The `color-mix()` function is an upcoming addition to the CSS Color Module Level 5 specification. Its primary purpose is to blend two or more colors together, generating a new color based on specified ratios. The blending process is dependent on the color space in which the colors are combined.

### Color Spaces: A Brief Overview

A color space is a specific organization of colors that allows for reproducible representations of these colors in both digital and physical mediums. There are several color spaces used in web design, each with its own unique characteristics:

- **RGB**: The Red-Green-Blue color space is an additive color model in which red, green, and blue light are combined in various ways to produce a broad range of colors. It is the most commonly used color space for digital images and web design.
- **HSL**: The Hue-Saturation-Lightness color space represents colors using three components: hue, saturation, and lightness. This color model is designed to be more intuitive and perceptually relevant than the RGB model.
- **LCH**: The Lightness-Chroma-Hue color space is a cylindrical representation of the CIELAB color space, which is designed to be perceptually uniform. LCH aims to provide a more accurate representation of how humans perceive color differences.
- **sRGB**: The standard Red-Green-Blue color space is a widely-used RGB color space that provides consistent color reproduction across various devices and platforms.

## Delving into the Syntax

The syntax for the `color-mix()` function is as follows:

```css
color-mix(<colorspace>, <color> <percentage>, <color> <percentage>, ...);
```

- `<colorspace>`: The color space in which the blending will occur. It can be one of the following: `srgb`, `display-p3`, `lab`, or `lch`.
- `<color>`: The colors to be mixed together. These can be specified using various color models, such as RGB, HSL, or LCH.
- `<percentage>`: The weight of each color in the mix. The sum of all percentages must equal 100%.

## A Comprehensive Exploration of Examples

To better understand the power and versatility of the `color-mix()` function, let's examine examples across various color spaces and color models.

### Example 1: Blending RGB Colors in sRGB Color Space

```css
:root {
  --cm-color-red: rgb(0 145 255);
  --cm-color-blue: rgb(0, 0, 255);
}

.rgb-srgb-mix {
  background-color: color-mix(
    srgb,
    var(--cm-color-red) 50%,
    var(--cm-color-blue) 50%
  );
}
```

In this example, we're blending equal parts saturated azure and blue (50% each) in the sRGB color space. The resulting color will be a neon blue.

{% codepen https://codepen.io/astrit/pen/PodrewQ %}

### Example 2: Blending HSL Colors in LCH Color Space

```css
:root {
  --cm-color-red: hsl(0, 100%, 50%);
  --cm-color-blue: hsl(240, 100%, 50%);
}

.hsl-lch-mix {
  background-color: color-mix(
    lch,
    var(--cm-color-red) 70%,
    var(--cm-color-blue) 30%
  );
}
```

Here, we're blending 70% red and 30% blue, represented in HSL, in the LCH color space. The resulting color will be a vibrant shade of pinkish-purple.

{% codepen https://codepen.io/astrit/pen/MWqMGKN %}

### Example 3: Blending LCH Colors in LCH Color Space

```css
:root {
  --cm-color-one: lch(50% 100 0);
  --cm-color-two: lch(50% 100 180);
}

.lch-lch-mix {
  color: color-mix(lch, var(--cm-color-one) 60%, var(--cm-color-two) 40%);
}
```

In this example, we're blending 60% of an LCH color with a lightness of 50%, chroma of 100, and hue of 0 degrees, with 40% of another LCH color with a lightness of 50%, chroma of 100, and hue of 180 degrees. The resulting color will be a bright shade of greenish-cyan.

{% codepen https://codepen.io/astrit/pen/gOdNzre %}

### Example 4: Working with Colors and Their Alpha Values

```css
.alpha-mix {
  background-color: color-mix(
    srgb,
    rgba(255, 0, 0, 0.5) 50%,
    rgba(0, 0, 255, 0.5) 50%
  );
}
```

In this example, we're blending equal parts red and blue with 50% alpha values in the sRGB color space. The resulting color will be a semi-transparent shade of purple.

{% codepen https://codepen.io/astrit/pen/LYJKmZx %}

### Example 5: Using CSS Custom Properties on the `:root`

```css
:root {
  --cm-brand-accent: lightseagreen;
  --cm-color: hsla(96, 78%, 45%, 1);
  --cm-color-a10: color-mix(in srgb, var(--cm-color), transparent 90%);
  --cm-color-a20: color-mix(in srgb, var(--cm-color), transparent 80%);
  --cm-color-a30: color-mix(in srgb, var(--cm-color), transparent 70%);
  --cm-color-a40: color-mix(in srgb, var(--cm-color), transparent 60%);
  --cm-color-a50: color-mix(in srgb, var(--cm-color), transparent 50%);
  --cm-color-a60: color-mix(in srgb, var(--cm-color), transparent 40%);
  --cm-color-a70: color-mix(in srgb, var(--cm-color), transparent 30%);
  --cm-color-a80: color-mix(in srgb, var(--cm-color), transparent 20%);
  --cm-color-a90: color-mix(in srgb, var(--cm-color), transparent 10%);
  --cm-color-dark: color-mix(in hsl, var(--cm-brand-accent), blue 10%);
}

.cm-a10 { color: var(--cm-color-a10) }
.cm-a20 { color: var(--cm-color-a20) }
.cm-a30 { color: var(--cm-color-a30) }
.cm-a40 { color: var(--cm-color-a40) }
.cm-a50 { color: var(--cm-color-a50) }
.cm-a60 { color: var(--cm-color-a60) }
.cm-a70 { color: var(--cm-color-a70) }
.cm-a80 { color: var(--cm-color-a80) }
.cm-a90 { color: var(--cm-color-a90) }
.cm-a00 { color: var(--cm-color) }

```

In this example, we're using CSS custom properties to define our base colors on the `:root` element. We then use the `color-mix()` function to change the transaprency based from the HSL color space, but it can be any color for that matter.

{% codepen https://codepen.io/astrit/pen/zYJVjKv %}

### Examole 6: Using calc function

The relative color syntax allows you to use channel keywords in any position for various purposes, such as creating a simple grayscale approximation of a color:

```css
:root {
  --cm-color: red;
  --cm-red-to-gray: rgb(
    from var(--color) calc(r * 0.3 + g * 0.59 + b * 0.11) calc(
        r * 0.3 + g * 0.59 + b * 0.11
      ) calc(r * 0.3 + g * 0.59 + b * 0.11)
  );
}

.cm-red-gray {
  color: var(--cm-red-to-gray);
}
```

This method converts colors like red to `rgb(30% 30% 30%)`, lime to `rgb(59% 59% 59%)`, and blue to `rgb(11% 11% 11%)`. However, this approach is not entirely accurate as it uses gamma-encoded space and obsolete NTSC color space weighting factors.

A more accurate and simpler way to grayscale a color is to use the `oklch()` function, which is better suited to human perception:

{% codepen https://codepen.io/astrit/pen/abagGBZ %}

```css
:root {
  --cm-color: red;
  --cm-oklch: oklch(from var(--color) l 0 h);
}

.cm-oklch {
  color: var(--cm-oklch);
}
```

This method preserves the lightness while zeroing out the chroma, which determines the colorfulness of the color.

{% codepen https://codepen.io/astrit/pen/rNZEvjV %}

## Leveraging the Color-Mix Function in Design Systems with Tokens and Figma Integration

Design systems are essential for maintaining visual consistency and streamlining the design process across large-scale projects. By incorporating the `color-mix()` function into a design system, we can enhance the flexibility and adaptability of color management.

### Benefits of Incorporating the Color-Mix Function into a Design System

Incorporating the `color-mix()` function into a design system can significantly improve the design process and provide various benefits for designers. Here are some advantages:

1. **Dynamic color manipulation**: The `color-mix()` function allows designers to create a wide range of color variations based on predefined color tokens. This flexibility makes it easier to manage and adjust colors within the design system, reducing the need for manual color adjustments.

2. **Adaptive color themes**: The `color-mix()` function can be used to generate color themes that adapt to different contexts, such as light and dark modes, by blending base colors with varying ratios. This adaptability simplifies the creation of context-aware designs and ensures visual consistency across different environments.

3. **Improved color consistency**: Using the `color-mix()` function to blend colors ensures consistency across the design system, as colors are derived from a set of predefined tokens. This consistency makes it easier for designers to maintain a cohesive visual language throughout the project.

4. **Efficient color exploration**: The `color-mix()` function enables designers to quickly explore various color combinations and find the perfect balance for their designs. This efficiency reduces the time spent on trial and error, allowing designers to focus on other aspects of the design process.

5. **Easier collaboration**: By integrating the `color-mix()` function into a design system, designers can share and collaborate on color schemes more effectively. This integration promotes a unified approach to color management and helps maintain visual coherence across large-scale projects involving multiple designers.

In conclusion, incorporating the `color-mix()` function into a design system can greatly enhance the design process, making it easier for designers to manage colors, create adaptive themes, and maintain visual consistency. By leveraging this powerful function, designers can focus on delivering a more polished and cohesive user experience.

## Browser Support for the CSS Color-Mix Function

As the `color-mix()` function is a relatively new addition to the CSS specification, it's important to be aware of the current state of browser support. Ensuring compatibility across different browsers is crucial for providing a consistent user experience.

### Current Browser Support

At the time of writing (knowledge cutoff in September 2021), the `color-mix()` function is not yet widely supported by major browsers. However, browser vendors are actively working on implementing this feature, and support is expected to improve over time.

To stay up-to-date with the latest browser support information, you can refer to resources such as [Can I use](https://caniuse.com/) and the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/CSS/color-mix). These platforms provide accurate and current details on browser compatibility for various web technologies, including the `color-mix()` function.

### Strategies for Handling Limited Browser Support

While waiting for broader browser support, you can employ several strategies to ensure your designs remain functional and visually consistent for users on unsupported browsers:

1. **Fallback styles**: Provide alternative color definitions for browsers that do not support the `color-mix()` function. Use the `@supports` rule in your CSS to detect support for the function and apply fallback styles accordingly.

   ```css
   .example {
     background-color: purple; /* Fallback color for unsupported browsers */
   }

   @supports (background-color: color-mix(srgb, red 50%, blue 50%)) {
     .example {
       background-color: color-mix(srgb, red 50%, blue 50%);
     }
   }
   ```

2. **Progressive enhancement**: Design your website with a basic color scheme that works well on all browsers, and then enhance the design with the `color-mix()` function for browsers that support it. This approach ensures that all users have a functional and visually appealing experience, regardless of their browser's capabilities.

3. **Polyfills**: Although there aren't any widely-used polyfills for the `color-mix()` function at the moment, you can keep an eye out for future developments in this area. Polyfills can help bridge the gap in browser support by providing a JavaScript-based implementation of the function for unsupported browsers.

### Conclusion

While browser support for the CSS `color-mix()` function is currently limited, it's essential to keep track of the latest developments in browser compatibility. By employing strategies such as fallback styles and progressive enhancement, you can ensure that your designs remain visually consistent and functional across different browsers. As support for the `color-mix()` function improves, it's expected to become an invaluable tool for web designers and developers in creating dynamic and adaptable color schemes.

#### Ref:

[CSS Color Module Level 5](https://w3c.github.io/csswg-drafts/css-color-5/#color-mix) — [MDN color-mix()](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix) — [Browser Support](https://caniuse.com/mdn-css_types_color_color-mix)

## Follow me: [Github](https://github.com/astrit) — [Youtube](https://youtube.com/@astrit)