Logo of The Bit Bang Theory blog

A Deep Dive Into Using Colors in CSS: Part 1

  ·  16 minutes read

Introduction

We define colors as a numeric or textual representation of the human visual perception of light—or, a physical object illuminated with it. We can quantify and physically describe human color perception through Colorimetry—the science of color measurement. It allows us to represent colors in numerical terms and to measure color differences between specimens. If two objects have different spectra but produce the same physical sensation, we say they have the same color.

Colors are an essential element of design and development and, as such, we have to thoroughly select them to have consistent results. There are a plethora of factors involving/impacting color definition, from cognitive load reduction to contrast accessibility, conveying intended meaning, and matching brand, system aesthetics, and user’s visual language. As a result, colors should not confuse or distract. Instead, they should draw attention where it needs to be and where appropriate and share honest, accurate information. Also, although colors can add significant information to documents and make them more readable, color by itself should not be the sole means to convey important information. We should always consider the W3C Web Content Accessibility Guidelines [WCAG21] when using color in our documents.


When it comes to CSS, there are distinct ways to denote colors. This article will walk you through defining colors via the following:

  • color keywords,
  • hexadecimal notation,
  • rgb(), hsl(), and hwb() color functions,
  • lab() and lch() functional notations for device-independent colors,
  • relative color syntax for the color functions above,
  • color() function and @color-profile at-rule for profiled, device-dependent colors,
  • and device-cmyk() function for device-dependent CMYK colors.

We will also review the color-mix() and color-contrast() functions from the CSS Color Module Level 5, which allow us to handle color modifications.

Throughout this article, we will test all these methods (where possible) with the same HTML boilerplate so we can get to visualize how each color notation works with the same content. Specifically, we will use the color, background-color, and border CSS properties to apply styles to the HTML content using the notations above.

Starter Code

As mentioned above, we will be using the same HTML content to apply CSS styles using different notations. The starter code below consists of an HTML file with a container wrapping two children elements (title and description). Some base CSS styles have also been provided to make it look a bit better.

Defining colors via color keywords

CSS outlines numerous sets of color keywords that can be used. From named colors to system colors, to the transparent and currentcolor keywords—they constitute the easiest and simple way to define colors in CSS.

Named colors

For the sake of simplicity, so that standard colors can be written and read more easily, CSS specifies a broad set of named colors. All of these named colors represent plain, solid colors, without any transparency. The colors are also ASCII case-insensitive and their values resolve to colors in the sRGB colorspace (we'll discuss colorspaces later in the article).

In the CSS world, there are basic named colors and extended named colors. All of these colors can always be rendered correctly, regardless of the color resolution available on the user’s display card.

It all started back in 1999 with the HTML 4.01 specification defining 16 color keywords (which, originally, came from the Windows VGA palette). Later, the CSS, Level 2 Revision 1 (CSS2.1) specification included orange for a total of 17 color keywords: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, orange, purple, red, silver, teal, white, and yellow.

On the other hand, the extended named colors—also called the X11 colors, or the SVG colors—come from one version of the X11 color system and are the result of merging specifications from HTML 4.01, CSS 2.0, SVG 1.0, and CSS3 User Interfaces (CSS3 UI).

The extended named colors comprise 140 colors, and along with their definitions, they constitute a superset of the list of named colors defined by SVG 1.1. You can also see the complete list on MDN.

The CSS spec outlines some curious facts regarding named colors:

These color names are standardized here, not because they are good, but because their use and implementation has been widespread for decades and the standard needs to reflect reality. Indeed, it is often hard to imagine what each name will look like (hence the list below); the names are not evenly distributed throughout the sRGB color volume, the names are not even internally consistent (darkgray is lighter than gray, while lightpink is darker than pink), and some names (such as indianred, which was originally named after a red pigment from India), have been found to be offensive. Thus, their use is not encouraged.

It's also worth mentioning that the CSS Colors Level 4 specification added the rebeccapurple keyword to honor web pioneer Eric Meyer.

Regarding their usage, it's as simple as setting the color keyword as the value for the property we would like to style. Just like we did with the basic styles of the starter code. On line 34 of the style.css file, we set the value of the description's background-color to gainsboro.

Upon reviewing these colors, you might have noticed that most of them are not particularly suitable for good aesthetics in regular web design. As a result, named colors are mostly used for testing and demonstration purposes.

System Colors

According to the CSS Color Module Level 4, system colors reflect default color choices made by the user, the browser, or the OS. They are typically used in the browser default stylesheet, for this reason. To maintain legibility, system colors also respond to light mode or dark mode changes.

We can use system color keywords for applying colors in the user’s color scheme. We can also use them with the forced-colors media query, for detecting an active forced color mode as well with the forced-color-adjust property, which controls whether user agent system theme colors overrides should be applied to an element and its descendants.

You can see all this in action in this great blog post by the Microsoft Edge Team: Styling for Windows high contrast with new standards for forced colors.

Earlier versions of CSS defined additional system colors, which have since been deprecated. These are documented in Appendix A: Deprecated CSS System Colors.

Also, note that by using system colors, you may incur in some privacy and security risk, as detailed in § 17 Security and Privacy Considerations.

The transparent keyword

The transparent keyword used to only be defined as an override value for the background and border properties until it was described as a true value by the CSS Color Module Level 3 specification. This keyword can be set on all properties and is widely supported among modern browsers including IE9+.

The transparent keyword resolves to a transparent black, which is a pure black, but fully transparent—i.e., rgb(0 0 0 / 0%). We'll review the rgb() function later on the article.

The currentcolor keyword

The currentcolor keyword resolves to the value of the color property on the same element, even if the color property changes across elements. Unlike named colors, it is not restricted to the sRGB colorspace; hence, its value can be any color. We can use the currentcolor keyword to set a color to the computed value of the element’s color property.

For simplicity, I will illustrate this with a very simple example:

.box {
  color: blue;
  background-color: currentcolor;
}

This is equivalent to:

.box {
  color: blue;
  background-color: blue;
}

The currentcolor keyword is useful to set a color on a property while keeping style consistency.

Casing style: currentcolor or currentColor?

The CSS spec anwsers this for us. Multi-word keywords in CSS usually separate their component words with hyphens. currentcolor doesn’t, because—deep breath—it was originally introduced in SVG as a property value, "current-color" with the usual CSS spelling. It (along with all other properties and their values) then became presentation attributes and attribute values, as well as properties, to make generation with XSLT easier. Then, all of the presentation attributes were changed from hyphenated to camelCase, because the DOM had an issue with hyphen meaning "minus". However, they didn’t follow CSS conventions anymore so all the properties and property values that were already part of CSS were changed back to hyphenated! currentcolor was not a part of CSS at that time, so it remained camelCased. Only later did CSS pick it up, at which point the capitalization didn't matter anymore, as CSS keywords are ASCII case-insensitive.

Color Terminology

Before diving into the rest of the CSS notations to define colors, there are some terms I'd like to explain and clarify for you, so you get the proper context and understanding of the content.

Color spaces

A color space is a specific organization of colors based on an underlying colorimetric model, such that there is a clear, objectively measurable meaning for any color in that color space. Color spaces help us understanding the color capabilities of a particular device or digital file.

This also means that the same color can be expressed in multiple color spaces, or transformed from one color space to another while looking the same. When trying to reproduce color on another device, color spaces can show whether you will be able to retain shadow/highlight detail, color saturation, and by how much either will be compromised.

sRGB Colors

According to the CSS Color Module Level 4 spec, CSS colors in the sRGB color space are represented by a triplet of values—red, green, and blue—identifying a point in the sRGB color space (SRGB). This is an internationally-recognized, device-independent color space, and so is useful for specifying colors that will be displayed on a computer screen, but is also useful for specifying colors on other types of devices, like printers.

CSS also allows the use of non-sRGB color spaces, as described in § 10.2 Predefined color spaces: srgb, display-p3, a98-rgb, prophoto-rgb, rec2020, xyz and lab'.

CSS provides several methods of directly specifying an sRGB color: hex colors, rgb()/rgba() functions, hsl()/hsla() functions, hwb() function, named colors, and the transparent keyword.

Additive color spaces

Additive color or additive mixing is a property of a color model that predicts the appearance of colors made by coincident component lights, i.e. the perceived color can be predicted by summing the numeric representations of the component colors.

An additive color space means that the coordinate system is linear in light intensity. The CIE XYZ color space is an additive color space (in addition, the Y component of XYZ is the luminance).

RGB uses additive color mixing, because it describes what kind of light needs to be emitted to produce a given color. RGB stores individual values for red, green and blue. RGBA is RGB with an additional channel, alpha, to indicate transparency. Common color spaces based on the RGB model include sRGB, Adobe RGB, ProPhoto RGB, scRGB, and CIE RGB.

Subtractive color spaces

Subtractive color or subtractive color mixing predicts the spectral power distribution of light after it passes through successive layers of partially absorbing media.

CMYK uses subtractive color mixing used in the printing process, because it describes what kind of inks need to be applied so the light reflected from the substrate and through the inks produces a given color. One starts with a white substrate (canvas, page, etc.), and uses ink to subtract color from white to create an image. CMYK stores ink values for cyan, magenta, yellow and black. There are many CMYK color spaces for different sets of inks, substrates, and press characteristics (which change the dot gain or transfer function for each ink and thus change the appearance).

For more information, refer to Wikipedia's List of color spaces and their uses

Chromaticity

Chromaticity is an objective specification of the quality of a color regardless of its luminance. Chromaticity consists of two independent parameters, often specified as hue (h) and colorfulness (s), where the latter is alternatively called saturation, chroma, intensity, or excitation purity. This number of parameters follows from trichromacy of vision of most humans, which is assumed by most models in color science.

Chromaticities are additive, so they accurately predict the chromaticity (but not the resulting lightness) of a mixture. Being two-dimensional, chromaticity is easily represented on a chromaticity diagram to predict the chromaticity of a color mixture. Any two colors can be mixed, and the resulting colors will lie on the line joining them on the diagram. Three colors form a plane, and the resulting colors will lie in the triangle they form on the diagram.

The RGB hexadecimal notation: #RRGGBB

Illustration explaining the structure of the RGB hexadecimal notation

The CSS RGB hexadecimal color notation, or hex notation, allows us to specify an sRGB color by providing the channels as hexadecimal numbers, which is comparable to how colors are often represented in computer code. It also provides us a shorter way to define colors, when compared to the rgb() functional notation.

But what are hexadecimal numbers? "In mathematics and computing, the hexadecimal (also base 16 or hex) numeral system is a positional numeral system that represents numbers using a radix (base) of 16. Unlike the common way of representing numbers using 10 symbols, hexadecimal uses 16 distinct symbols, most often the symbols 0 through 9 to represent values 0 to 9, and A through F (or af) to represent values 10 to 15."

The syntax of the hex color notation declares a value consisting of 3, 4, 6, or 8 hexadecimal digits. These digits represent each of the primary colors (red, green, and blue) in intensity from 0, represented as 00, up to 255, represented as ff. In other words, a hex color is written as a hash character, #, followed by some number of digits 0-9 or letters a-f (the case of the letters doesn’t matter - #ff0000 is identical to #FF0000).

The hex color notation is, probably, the most used method to define colors in CSS. However, it's not the most human readable one. Using this method, we can represent an sRGB color in four different ways. The number of hex digits given determines how to decode the hex notation into an RGB color:

6 digits: #ff0000

The first pair of digits, interpreted as a hexadecimal number, specifies the red channel of the color, where 00 represents the minimum value and ff (255 in decimal) represents the maximum. The next pair of digits, interpreted in the same way, specifies the green channel, and the last pair specifies the blue channel.

8 digits: #ff0000cc

The first 6 digits are interpreted identically to the 6-digit notation. The last pair of digits, interpreted as a hexadecimal number, specifies the alpha channel of the color, where 00 represents a fully transparent color and ff represent a fully opaque color.

3 digits: #f00

This is a shorter variant of the 6-digit notation. The first digit, interpreted as a hexadecimal number, specifies the red channel of the color, where 0 represents the minimum value and f represents the maximum. The next two digits represent the green and blue channels, respectively, in the same way.

4 digits: #f00c

This is a shorter variant of the 8-digit notation, expanded in the same way as the 3-digit notation is. The first digit, interpreted as a hexadecimal number, specifies the red channel of the color, where 0 represents the minimum value and f represents the maximum. The next three digits represent the green, blue, and alpha channels, respectively.

Applying the hex notation to our sample code

Now, let's use this notation in our sample code by replacing all the colors we previously defined (via name colors) with colors specified with the hex notation.

We've added a background-color style to the container element as well.

The rgb() color function

The rgb() function defines an sRGB color by specifying the red, green, and blue channels directly.

Illustration explaining the syntax of the RGB functional notation

First, let me clarify that I'm using the new syntax here, which was introduced to make existing functions consistent with the syntax used for new functions such as lab() and lch().

As the spec outlines, the first three arguments specify the red, green, and blue channels of the color, respectively. 0% represents the minimum value for that color channel in the sRGB gamut, and 100% represents the maximum value. A number is equivalent to a percentage, but with a different range: 0 again represents the minimum value for the color channel, but 255 represents the maximum. These values come from the fact that many graphics engines store the color channels internally as a single byte, which can hold integers between 0 and 255. Implementations should honor the precision of the channel as authored or calculated wherever possible.

The final argument, the alpha value (α), specifies the opacity/transparency of the color. If given as a number, the useful range of the value is 0 (representing a fully transparent color) to 1 (representing a fully opaque color). If given as a percentage, 0% represents a fully transparent color, while 100% represents a fully opaque color. If omitted, it defaults to 100%. Values outside these ranges are not invalid, but are clamped to the ranges defined here at computed-value time.

Legacy syntax and the rgba() function

As I mentioned above, a new syntax was introduced for the rgb() function. The older syntax made use of commas (,) to separate values, which is no longer needed since the new syntax specify space separated values. As for transparency, we used to use a legacy function: rgba(), which works exactly like the rgb() function but also accepts a fourth value as the value for the alpha channel, i.e., for transparency. Both the old syntax and the rgba() function still exist for compatibility reasons.

Here's a brief summary/comparison of old vs new syntaxes:

Type Old Syntax New Syntax
RGB rgb(173, 240, 36) rgb(173 240 36)
RGBa rgb(173, 240, 36, 0.4) rgb(173 240 36 / 0.4)

As for support, the new syntax has been broadly implemented, with the exception of Internet Explorer, of course.

Using the rgb() functional notation in our sample code

To make use of the rgb() functional notational, we first need to convert the colors from hex notation to RGB (we declared them as hex in the previous section). To do so, we'll make use of the DuckDuckGo's built-in color converter tool.

The hsl() color function

HSL (hue, saturation, lightness) is a color scheme designed in the 1970s as an alternative representation of the RGB color model. It was designed to more closely align with the way human vision perceives color-making attributes. As previously mentioned, the RGB system for specifying colors, while convenient for machines and graphic libraries, is often regarded as very difficult for humans to gain an intuitive grasp on. It’s not easy to tell, for example, how to alter an RGB color to produce a lighter variant of the same hue.

In the HSL color model, colors of each hue are arranged in a radial slice, around a central axis of neutral colors which ranges from black at the bottom to white at the top. As a result, the HSL color scheme is much more intuitive to use while still mapping easily back to RGB colors, so HSL colors resolve to sRGB.

According to the spec, HSL colors are specified as a triplet of hue, saturation, and lightness. The syntax of the hsl() function is:

Illustration explaining the syntax of the HSL functional notation

The first argument specifies the hue angle. In HSL (and HWB) the angle 0deg represents sRGB primary red (as does 360deg, 720deg, etc.), and the rest of the hues are spread around the circle, so 120deg represents sRGB primary green, 240deg represents sRGB primary blue, etc.

The next two arguments are the saturation and lightness, respectively. For saturation, 100% is a fully-saturated, bright color, and 0% is a fully-unsaturated, gray color. For lightness, 50% represents the normal color, while 100% is white and 0% is black. If the saturation or lightness are less than 0% or greater than 100%, they are clamped to those values at computed value time, before being converted to an sRGB color.

The final argument specifies the alpha channel of the color. It’s interpreted identically to the fourth argument of the rgb() function. If omitted, it defaults to 100%.

Illustration depicting the HSL color cylinder

HSL cylinder. Taken from Wikipedia.

One advantage of HSL over RGB is that it is more intuitive: we can select any base color we want, and play around with its saturation and lightness to obtain shades and tints.

hsl(219deg 60% 96%)Ultra Light Blue

hsl(219deg 60% 72%)Light Blue

hsl(219deg 60% 48%)Base Blue

hsl(219deg 60% 24%)Dark Blue

hsl(219deg 60% 8%)Ultra Dark Blue

Notice we didn't alter the hue in the previous example, since the hue angle in HSL is not perceptually uniform; colors appear bunched up in some areas and widely spaced in others, which constitute one of the disadvantages of HSL over LCH: hue manipulation changes the visual lightness. Let's see this more clearly with an example provided by the specification:

Consider the following pair of hues:

hsl(220deg 100% 50%)

hsl(250deg 100% 50%)

These two colors have an HSL hue difference of 30deg yet they look fairly similar, while the pair of colors below, which also have a hue difference of 30deg, look absolutely different.

hsl(50deg 100% 50%)

hsl(80deg 100% 50%)

Using the hsl() function in our sample code

To make use of the hsl() functional notational, we first need to convert the colors from rgb() notation (from the previous section) to HSL. I've done this already, by using a JavaScript conversion algorithm.

Legacy syntax and the hsla() function

Similar to the case of the rgb() function, a new syntax was introduced for the hsl() function. The new syntax requires no use of commas but spaces to separate values. As for transparency, there is the hsla() legacy function, which works exactly like the hsl() function but also accepts a fourth value as the value for the alpha channel, i.e., for transparency. Both the old syntax and the hsla() function still exist for compatibility reasons.

Here's a brief summary/comparison of old vs new syntaxes:

Type Old Syntax New Syntax
HSL hsl(219deg, 60%, 48%) hsl(219deg 60% 48%)
HSLa hsla(219deg, 60%, 48%, 0.8) hsl(219deg 60% 48% / 80%)

As for support, the new syntax has been broadly implemented, with the unsurprising exception of Internet Explorer.

The hwb() color function

HWB (hue, whiteness, blackness) is a cylindrical-coordinate representation of points in an RGB color model, similar to HSL. According to its creator, Alvy Ray Smith, the HWB color model "was designed to be more intuitive for humans to use and slightly faster to compute."

HWB colors are specified as a triplet of hue, whiteness, and blackness. The syntax of the hwb() function is:

Illustration explaining the syntax of the HWB functional notation

Similar to HSL colors, HWB colors resolve to sRGB.

The first argument specifies the hue, and is interpreted identically to hsl().

The second argument specifies the amount of white to mix in, as a percentage from 0% (no whiteness) to 100% (full whiteness). Similarly, the third argument specifies the amount of black to mix in, also from 0% (no blackness) to 100% (full blackness). Values outside of these ranges are not invalid, but are clamped to the ranges defined here at computed-value time. If the sum of these two arguments is greater than 100%, then at computed-value time they are further normalized to add up to 100%, with the same relative ratio.

The fourth argument specifies the alpha channel of the color. It’s interpreted identically to the fourth argument of the rgb() function. If omitted, it defaults to 100%.

The resulting color can be thought of conceptually as a mixture of paint in the chosen hue, white paint, and black paint, with the relative amounts of each determined by the percentages. If the used amount of white plus the used amount of black is equal to 100% (after normalization), it defines an achromatic color, i.e. some shade of gray, without any hint of the chosen hue.

Unfortunately, we won't be using the hwb() functional notation on our sample code since it has yet to be implemented in any browser. Mozilla bug: 1352755

Device-independent colors: Lab and LCH

When introducing the hsl() functional notation, I highlighted one advantage of HSL over RGB: it is more intuitive. In fact, in the web development world, many developers have argued that HSL is fairly easier to work with than RGB or hex values. However, despite HSL being easier to understand and use, it's got its flaws. The way it calculates lightness doesn’t exactly match human visual perception. We saw this with examples of different pair of colors with an HSL hue difference of 30deg yet looking either similar or totally different. A color space with better lightning management was needed.

Looking for a precise representation of the human color perception, the International Commission on Illumination created the CIELAB color space (also referred to as Lab*, or simply Lab).

CIELAB color space front view

CIELAB color space front view.

Created back in 1976, the CIELAB color space models the entire range of color that humans can see by expressing color as three values: L* for perceptual lightness, and a* and b* for the four unique colors of human vision: red/green and blue/yellow, respectively.

CIELAB color space diagram

CIELAB color space diagram.

CIELAB was intended as a perceptually uniform space, where a given numerical change corresponds to similar perceived change in color. This means that if we provide two colors the same value for lightness, they will appear—to the human eye—to have the same lightness, regardless of their hue.

CIELAB color space top view

CIELAB color space top view.

The CIELAB colorspace is a device-independent, "standard observer" model. The colors it defines are not relative to any particular device such as a computer monitor or a printer, but instead relate to the CIE standard observer which is an averaging of the results of color matching experiments under laboratory conditions.

CIELAB Coordinates

CIELAB is a 3D color space that covers the entire range of human color perception, or gamut. It is based on the opponent color model of human vision, where red/green forms an opponent pair, and blue/yellow forms an opponent pair as well. The lightness value, L*, also referred to as "Lstar," defines black at 0 and white at 100. The a* axis is relative to the green–red opponent colors, with negative values toward green and positive values toward red. Whereas, the b* axis represents the blue–yellow opponents, with negative numbers toward blue and positive toward yellow.

The CSS Color Module Level 4 specification further explains this as follows: Lab is a rectangular coordinate system with a central Lightness axis. This value is usually written as a unitless number; for compatibility with the rest of CSS, it is written as a percentage. 100% means an L value of 100, not 1.0. L=0% is deep black (no light at all) while L=100% is a diffuse white.

Values of L greater than 100 would correspond to specular highlights, but their precise color is undefined in the specification. Usefully, L=50% is mid gray, by design, and equal increments in L are evenly spaced visually: the Lab color space is intended to be perceptually uniform.

Show the L axis of CIE Lab color space. 0% 10% 20% 30% 40% 50% 60% 70% 80% 90% 100%

Lightness axis of the CIE Lab color space. Twenty neutral swatches are shown (L=0%, L=5%, to L=100%). The steps are equally spaced, visually. Taken from the CSS Color Module Level 4 spec.

The a* and b* axes convey hue; positive values along the a axis are a purplish red while negative values are the complementary color, a green. Similarly, positive values along the b axis are yellow and negative are the complementary blue/violet. Desaturated colors have small values of a* and b* and are close to the L* axis; saturated colors lie far from the L* axis.

CIELAB is calculated relative to a reference white, for which the CIE recommends the use of CIE Standard Illuminant D65. In the case of the CSS implementation, however, the illuminant is D50, a standardized daylight spectrum with a color temperature of 5000K, as reflected by a perfect diffuse reflector; it approximates the color of sunlight on a sunny day.

LCH has the same L axis as Lab, but uses polar coordinates C (chroma) and H (hue), making it a polar, cylindrical coordinate system. C is the geometric distance from the L axis and H is the angle from the positive a axis, towards the positive b axis.

Show the L=50 plane of the CIE Lab color space. 20 degree increments in CIE LCH are converted to Lab, then displayed as circles with the cx coordinate = CIE a and. The cy coordinate = CIE (-b) to give a Y-up coordinate system. Three levels of Chroma are displayed: 20, 40 and 60. All the C=20 fit inside sRGB gamut, some of C=40 and C=60 are outside. The colors are converted to sRGB which is used to fill the circles. The out of gamut circles are visualized as grey with a red warning outer stroke. +a -a -b +b

L=50 plane of the CIE Lab color space. 20 degree increments in CIE LCH are displayed as circles at three levels of Chroma: 20, 40 and 60. All the 20 Chroma colors fit inside sRGB gamut, some of 40 and 60 Chroma are outside. These out of gamut colors are visualized as grey, with a red warning outer stroke.

As indicated on the spec, CSS allows colors to be directly expressed in Lab and LCH. Let's take a look at how to define colors with these syntaxes.

The lab() functional notation

Illustration of the lab() functional notation

The syntax of the lab() functional notation.

The first argument specifies the CIE Lightness. This is usually a number between 0% (representing black) and 100% (representing white), However, CIE Lightness can exceed this range on some systems, with extra-bright whites using a lightness up to 400. Values less than 0% must be clamped to 0% at computed-value time; values greater than 100% are permitted—for forwards compatibility with HDR—and must not be clamped.

The second and third arguments are the distances along the a* and b* axes in the Lab color space, as described in the previous section. These values are signed (allow both positive and negative values) and theoretically unbounded. In practice, though, they do not exceed ±160.

There is an optional fourth alpha value, separated by a slash, and interpreted identically to the in the rgb() function.

lab(29.2345% 39.3825 20.0664)

lab(52.2345% 40.1645 59.9971)

lab(60.2345% -5.3654 58.956)

lab(62.2345% -34.9638 47.7721)

lab(67.5345% -8.6911 -41.6019)

The lch() functional notation

Illustration of the lch() functional notation

The syntax of the lch() functional notation.

The first argument specifies the CIE Lightness, interpreted identically to the Lightness argument of lab().

The second argument is the chroma (roughly representing the "amount of color"). Its minimum useful value is 0, while its maximum is theoretically unbounded (but in practice does not exceed 230). If the provided value is negative, it is clamped to 0 at computed-value time.

The third argument is the angle. It’s interpreted similarly to the argument of hsl() function, but doesn’t map hues to angles in the same way because they are evenly spaced perceptually. Instead, 0deg points along the positive a* axis (toward purplish red), (as does 360deg, 720deg, etc.); 90deg points along the positive b* axis (toward mustard yellow), 180deg points along the negative a* axis (toward greenish cyan), and 270deg points along the negative b* axis (toward sky blue).

There is an optional fourth alpha value, separated by a slash, and interpreted identically to the in rgb().

lch(29.2345% 44.2 27)

lch(52.2345% 72.2 56.2)

lch(60.2345% 59.2 95.2)

lch(62.2345% 59.2 126.2)

lch(67.5345% 42.5 258.2)

Note: The examples above have been taken from the CSS Color Module 4 Specfication.

Regarding the usage of these notations on our sample code, we won't be able to do this at this moment given the lack of implementation of these syntaxes on the browsers I have access too. If you have access to Safari, howver, you will be able to try them.


That's all for part one of this series. Read on part 2 where we review Profiled, Device-dependent Colors, Predefined color spaces, Relative color syntax, the @color-profile at-rule as well as the color(), device-cmyk(), color-mix(), and color-contrast() functions.

Back to Home