lab()

Sunkanmi Fafowora on

Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.

The lab() function represents colors in the CIELAB (also known as CIE L*a*b*) color space. It displays them according to their lightness, red/green axis position, blue/yellow axis position, and an optional alpha transparency value.

.element {
  color: lab(50% 50% 50% / 0.5);
}

The lab() color function is defined in the CSS Color Module Level 4 and Level 5 specifications.

Syntax

Unlike the rgb() and hsl() functions, lab() can only be written as a space-separated list, so use spacesnot commas.

lab( [<percentage> | <number> | none]
      [ <percentage> | <number> | none]
      [ <percentage> | <number> | none]
      [ / [<alpha-value> | none] ]? )

<alpha-value> = <number> | <percentage>

Arguments

/* Integer and decimal values ranging from 0 - 100 for l, and -125 - 125 for a and b */
.element {
  color: lab(35 50 95.5);
}

/* Percentages ranging from 0% - 100% */
.element {
  color: lab(25% 5% 45%);
}

/* `none` can be specified for any channel */
.element {
  color: lab(6% none none);
}

/* Optional decimal value for transparency */
.element {
  color: lab(0 0 0 / 0.5);
}

/* Optional percentage value for transparency */
.element {
  color: lab(0 0 0 / 50%);
}

/* Using relative colors */
.element {
  color: lab(from green 50 a b / 0.5);
}
  • l value: Represent the lightness and ranges from 0% or 0.0 to 100% or 100.0. Since l represent the lightness, 0% adds more black and 100% adds more white.
  • a value: It takes both positive and negative values from -125 to 125 or -100% to 100%a represents the color’s position in the red/green axis, setting the amount of green (-125/-100%) or red (125/100%) contained in the color.
  • b value: It takes both positive and negative values from -125 to 125 or -100% to 100%b represents the color’s position in the blue/yellow axis, setting the amount of green (-125/-100%) or red (125/100%) contained in the color.
  • <alpha-value>: Sets the transparency and can be any decimal value between 0 to 1.0 (e.g. 0.8) or any percentage from 0% and 100%.

Theoretically, axis values (a and b) have no upper or lower limit, but the spec says colors past -160 or 160 have a negligible difference. However, after testing on Chrome and Firefox, I noticed colors still get generated even after that threshold.

Unlike hsl() which has a rotating hue, lab() doesn’t circle back to its first value, hence, it truly doesn’t have upper or lower limits.

Understanding lab()

You can think of each channel in lab() as an axis between two colors, moving from one side to another to get more or less from that color. For example, we can imagine l as an axis between white and black, where 0 adds more black and 100 adds more white. The a channel does the same with an axis going from green (-125) to red (125), while b goes from blue (-125) to yellow (125).

It’s odd at first how l goes from 0 to 100 while the rest of the axes go to 125 and even have negative values. Remember, though, that l also represents lightness, where 0 is the absence of light and we can’t go below that. So, it ends up making sense.

The l value is generally considered to be achromatic (without any color, including black, white, or gray), while a and b are considered to be chromatic (with color, so no hint of black, white, or gray).

So if we have three axes, we can then imagine a 3D plane of color that we can navigate using lab():

CIELAB Color space representation from DataColor

Remember how we mentioned that the values don’t have upper or lower limits? CIELAB — the color space navigated with lab() — closely covers the entire gamut of colors seen by the human eye, and while it can be used to represent colors beyond that, due to screen limitations (and sometimes even our own eyes) they aren’t perceivable. In contrast, the rgb() color function — which is mapped to the sRGB color space — can only represent a subset of those colors:

Image from The MVP Blog

This means lab() has access to a richer palette of color than sRGB-based functions such as rgb() and hsl().

Basic usage

To recap, lab() has three main arguments in a space-separated list. First, l sets the lightness ranging from 0 to 100, then a sets the value in the greenness-to-redness axis from -125 to 125, and lastly b does the same with the blueness-to-yellowness axes from -125 to 125. And if you need to mingle with the color’s transparency, we can write a slash (/) followed by the transparency value formatted as a decimal between 0 to 1, or as a percentage between 0% and 100%.

It can be used in the same places you use your rgb() or hsl() functions, meaning any CSS property that accepts a color value:

.element {
  color: lab(10 195 10 / 0.5);
}

This color function is ideal if you’re looking to represent or select colors that are not available in rgb() or hsl(). In other words, if you are attempting to use a color that falls outside the range of what is offered in the sRGB color space, then try using lab() for access to a wider range of colors.

Relative colors

The CSS lab() function supports the relative color syntax, which means it can be used to convert a color from one color space into another color in another color space. Here’s how it works:

.element {
  color: lab(from hsl(10% 50% 50%) l a 40);
}

To use it, you need to include the from keyword followed by any color (it can be another color function or a named color), then replace any of its values with its corresponding channel letter (in this case, l for lightness, a for the red/green axis, b for the blue/yellow axis, and the optional alpha for the alpha value), and they will take on the value from the original color.

A quick demo below shows the colors produced by rgb() inside lab():

.element {
  background-color: lab(from rgb(155 100 250) l a b);
}

And the other way around, we can translate lab(), which operates in the CIE Lab* color space, to the sRGB color space to be used by sRGB-based functions rgb()hsl() or hwb().

Color gradient with lab()

Colors created with lab() usually look more beautiful and vibrant, exploding with color and representing corners of the CIE Lab* color space that hsl() and rgb() could ever dream of. One specific case further proves this: gradients.

Without getting too detailed, let’s make two two-color gradients from colors in the sRGB color space using rgb() and hsl() and compare it to a two-color gradient using colors from the CIE Lab* color space using the lab() function:

See the difference? lab() is brighter and more vibrant than hsl() and rgb(). Some may even say they look “washed” especially when passing through sRGB’s dead gray zone, which is caused by the lack of access to more color.

Math functions can be used in lab()

You can use math functions in hsl() to manipulate a color stored in a custom property:

.element {
  background-color: lab(
    calc(var(--my-l-value) + 40) calc(var(--my-a-value) + 10) var(--my-b-value) / calc(var(--my-alpha-value) + 0.1)
  );
}

It can even be used to change each channel after using the relative color syntax:

.element {
  background-color: lab(from hsl(30deg 50 10%) calc(l + 60) calc(a + 30) b);
}

In the example above, I’m using the calc() function to add 60 more points to the l channel and 30 more to the a channel. Here’s what this looks like in the demo below:

Demo

Here’s a demo showing how the lab color function works with a conic gradient. Change the values to update the color scheme and see how each value influences the overall color:

Specification

The lab() function is defined in the CSS Color Module Level 4 specification, while the relative syntax using channel letters is defined in the CSS Color Module Level 5 specification. Both are currently in Editor’s Draft status at the time of writing. This means changes can still be made to this function in the future.

Browser support

More information