Colour Functions

To be able to utilise the newer colour spaces we now have available in CSS, we need to use a colour function. A colour function is made up of your chosen colour space followed by a set of 3 or sometimes 4 numbers within a pair of parenthesis. Within each of the 3 main Colour spaces that are supported by modern browsers sRGB, CIELAB and OkLab, we have further colour spaces and functions which access the full range of colours within those spaces differently.

sRGB Colour Space Functions

The original standard colour space which is still relevant and most widely used today in the digital world, especially now with the newer functions like hsl that gives you better control over colour picking.

rgb() & rgba() = (red 0-255, green 0-255, blue 0-255 / alpha 0.0-1.0) alpha is the colours opacity

hsl() & hsla() = (hue 0-360 or 0deg-360deg, saturation 0-100 or 0-100%, lightness 0-100 or 0-100% / alpha 0.0-1.0 or 0-100%)

hwb() = (hue 0-360, whiteness 0-100, blackness 0-100 / alpha 0.0-1.0)

CIELAB Color Space Functions

This newer colour space on the web represents a wider colour gamut, and is also closer to what the human eye sees than the sRGB space.

lab() = (lightness 0-100, greenness to redness -125 to 125, blueness to yellowness -125 to 125)

lch() = (whiteness to blackness 0-100, chroma 0-150, hue 0-360 / alpha 0.0-1.0 or 0-100%)

OkLab Color Space Functions

Only introduced in 2020 by Bjorn Ottosson this colour space aims to improve on the lab() spaces, with its perceptual uniformity which helps with predicting hue and lightness easier, providing much smoother colour blending for gradients.

oklab() = (whiteness to blackness 0.0-1.0 or 0-100%, greenness to redness -0.4 to 0.4 or -100 to 100%, blueness to yellowness -0.4 to 0.4 or 0 to -100%/ alpha 0.0-1.0)

oklch() = (whiteness to blackness 0.0-1.0 or 0-100%, chroma 0-0.4 or 0-100%, hue 0-360 or 0deg-360deg / alpha 0.0-1.0 or 0-100%)

Its also now possible to access many more colour spaces than these, since the introduction of color() and color-mix() functions.

Further color() References

MDN - color value

The color() function

The color() function has opened up the ability to define a wider gamut of colours from many more colour spaces, unlike previously where we could only access the default sRGB space.

The function syntax allows you to name the colour space you want to use as well as plotting three colour value co-ordinates, and the opacity. Opening up a whole new world of colours which can be rendered with more precision.

Colour spaces available to use with this function are srgb, srgb-linear, display-p3, a98-rgb, prophoto-rgb, rec2020, xyz, xyz-d50, and xyz-d65

body {
    color(colorspace c1 c2 c3 / a)
}
/* function(named colorspace | 3 x co-ordinates 0-1 | alpha 0-1 or 0%-100%) */
  • 1. Open the color() function
  • 2. Specify the colorspace your colour is from
  • 3. Followed by the colours three value co-ordinates each can be written as a number between 0.0 - 1.0 (values outside of these are permitted, but will be outside of the given colour space's gamut), a percentage 0% - 100%, or the keyword none (equivalent of 0)
  • 4. Finally the opacity (which is an optional value), this is the alpha number which is either a value between 0.0 - 1.0 or a percentage between 0% - 100%

Color() Function Resources & References

Further reading on color function:

CSS Tricks CSS Color Functions by Sunkanmi Fafowora

CSS Tricks CSS Functions Guide by Eric Bailey

MDN Docs color()

MDN Blog Relative Color Syntax — Basic Use Cases by Brian Smith

color-relative function

This color-relative syntax allows you to take any base colour along with any given colour function, and modify it to create other colours and variants. These can be either lighter, darker, saturated, semi-transparent, or even inverted.

It does this by taking your chosen colour format and creating a colour function using the from keyword. With this CSS colour function you can now manipulate any part of your base colour to create a shade of the original, or a whole different colour.

color-function(from origin-color channel1 channel2 channel3)
color-function(from origin-color channel1 channel2 channel3 / alpha)

/* color space included in the case of color() functions */
color(from origin-color colorspace channel1 channel2 channel3)
color(from origin-color colorspace channel1 channel2 channel3 / alpha)

Color-relative Resources & References

Further reading on color-relative functions:

Chrome for Developers CSS relative color syntax by Adam Argyle

MDN Relative colors

Frontend Masters Relative Color Syntax — Basic Use Cases by Chris Coyier

Jims Blog Dynamic Color Manipulation with CSS Relative Colors by Jim Nielsen

color-mix() function

The color-mix() function now allows you to mix your very own colours in CSS!!

By taking two colour values from within a specified colour space, we can create so many more colours. Plus when we adjust the dominance of these colours by setting either one or both of their percentage values, we can create even more colour shades.

The process used to mix the two colours is called colour interpolation. Which is the process of finding a precise colour point, between the two colour values, within a specified colour space.

color-mix syntax

The color-mix syntax starts with the color-interpolation-method consisting of the in keyword followed by the colour space and a comma. Further followed by comma separated colour values, with optional percentage values.

color-mix(<color-interpolation-method>, <color>[<percentage>], <color>[<percentage>])

color-mix(in srgb, red, blue);
color-mix(in srgb-linear, red, blue);
color-mix(in lch, red, blue);
color-mix(in oklch, red, blue);
color-mix(in lab, red, blue);
color-mix(in oklab, red, blue);
color-mix(in xyz, red, blue);

srgb

srgb-linear

lch

oklch

lab

oklab

xyz

The color-interpolation-method will accept any of the colour spaces, but which one you use will effect the resulting colour:

  • <rectangular-color-space>: srgb, srgb-linear, display-p3, a98-rgb, prophoto-rgb, rec2020, lab, oklab, xyz, xyz-d50, and xyz-d65.
  • <polar-color-space>: hsl, hwb, lch, and oklch.
  • <hue-interpolation-method>: Specifies how the midpoint between the colours in a polar colour space are found. This can either be the shorter hue, longer hue, increasing hue, or decreasing hue. A way to visualise this, is to imagine you're looking at a colour wheel. The midpoint for the shorter hue, would be the side of the wheel with the shortest distance between your two colour values, and the longer hue would be on the side with the longest distance between the values.

Though the default colour space, which provides the best and consistent colour results for mixing colours (and gradients) is oklab.

calculating color-mix

As we have already mentioned as well as mixing two colours we can also control how much of each colour is in the mix. By default the colour values within a color-mix calculation will be of equal value.

color-mix(in oklab, red, white);
/* is the same as writing */
color-mix(in oklab, red 50%, white 50%);

But we can control which of the colours will be the dominant one within the mix, by adding a percentage or higher percentage to it. Any percentage value between 0 - 100% can be added to either one or both colours. With 0% being no colour at all, to 100% being a full bold solid colour.

/* with colour percentage set */
color-mix(in oklab, red 60%, white);
/* is the same as writing */
color-mix(in oklab, red 60%, white 40%);

red 60%, white

red 60%, white 40%

Because the color-mix function automatically calculates everything to a 100%, its not always necessary to add both percentages. As the code example above shows, if we specify the red value to be 60% and nothing for the white, the color-mix function will automatically calculate the white to be 40%.

/* equal percentages > 100% are equally clamped */
color-mix(in oklab, red 85%, white 85%);
/* is the same as writing */
color-mix(in oklab, red 50%, white 50%);


/* total values that are > 100% */
color-mix(in oklab, blue 75%, white 50%);

/* is recalculated and the same as writing */

color-mix(in oklab, blue 60%, white 40%);
/* Add percentages 75 + 50 = 125 */
/* 1st value: 75 x 100 = 7500 / 125 = 60 (or 60%) */
/* 2nd value: 50 x 100 = 5000 / 125 = 40 (or 40%) */

red 85%, white 85%

red 50%, white 50%

blue 75%, white 50%

blue 60%, white 40%

So what happens if the colour percentages add up to more than 100%?

Well, the function will make a calculation. First it adds the two percentage values together, then multiplies each percentage by 100 before dividing this value by the first.

/* total added percentages = < 100% */

/* 60 + 10 = 70% so 100 - 70 = 30% alpha transparency */
color-mix(in oklab, purple 60%, white 10%);

/* 30 + 20 = 50% so 100 - 50 = 50% alpha transparency */
color-mix(in oklab, purple 30%, white 20%);

purple 60%, white 10%

purple 30%, white 20%

But what if the total value of the colours is less, than the 100%?

Then the alpha value that controls opacity / transparency comes into the calculation. As demonstrated in the above code example, when the two colour percentage values are added together and then their total taken away from 100%, the remaining number is the Alpha value or the percentage of the colours transparency.

/* Nesting colour spaces */
color-mix(in lch, yellow 30%, color-mix(in oklab, skyblue, hotpink))

yellow 30%, color-mix(skyblue, hotpink)

Its also possible to nest colour spaces too, which opens up even more colour possibilities for us to explore!!!

Color-mix Resources & References

Here's some blog articles & docs on color-mix functions we found useful and informative:

MDN - color-mix()

Chrome for Developers - CSS color-mix() by Adam Argyle

CSS Tricks - color-mix() by Sunkanmi Fafowora

Gradients

Until now, making a smooth transitioned gradient has almost felt like taming a mystical creature or trying to understand rocket science!

But now with the help of colour functions we have the ability to create seamless gradients so much easier. By adding our own choice of colour spaces, precisely plotting colour values and being able to manipulate a colour spaces hue. It provides us more control over the transition of colours, resulting in a gradient that is smoother and better blended..

.original_gradient {
   background: linear-gradient(to right, skyblue, hotpink);
}

.adding_a_colorspace {
  background: linear-gradient(to right in hsl, skyblue, hotpink);
  background: linear-gradient(to right in oklab, skyblue, hotpink);
  background: linear-gradient(to right in oklch, skyblue, hotpink);
}

Default (srgb)

hsl

oklab

oklch

As we can see from the above examples, which colour space we use can make a dramatic difference to the resulting gradient, from the transition of the colours, to their vibrancy.

.a_step_further {
  background: linear-gradient(to right in oklch, hsl(200.44deg 50% 50%),  hotpink);
  background: linear-gradient(to right in hsl, hsl(200.44deg 50% 50%),  hotpink);
  background: linear-gradient(to right in hsl, hsl(100deg 50% 50%),  hotpink);
}

mixing colour spaces oklch & hsl

specifying hsl colour space & colour value

with one colour value tweak

Its also possible, to mix & match your colour spaces within your linear-gradient, again we can see how using different colour spaces can effect the transition of colours in a gradient.

We can also just tweak a single value of a gradients colours, to totally change the resulting gradient. Here in this example we've only adjusted the deg value of our specified hsl colour from 200.44deg to 100deg and we have a very different coloured effect.

.adding_the_hue_value {
  background: linear-gradient(to right in hsl longer hue, skyblue, hotpink);
  background: linear-gradient(to right in hsl shorter hue, skyblue, hotpink);
}

Longer

Shorter

We can also manipulate the hue value within a colour space to create very different gradients. By stating the direction the hue value travels between our two colour values.

.a_single_colour_rainbow {
  background: linear-gradient(to right in hsl shorter hue, skyblue, skyblue);
  background: linear-gradient(to right in hsl longer hue, skyblue, skyblue);
}

Shorter

Longer

Now that we can add colour spaces and then manipulate its hue within a linear-gradient, we can even create a full on rainbow by only using a single repeated colour value. Though if you state the wrong direction for your hue will result in a single block of colour, so be careful.

Page Last Edited: