From color perception to CSS

From color perception to CSS

Written by: Szymon Walczak, Frontend Developer


Check out our latest open job positions and apply!

Join Espeo Software

Color perception

The way humans perceive colors is not universal. Rather, we are capable of comparing and contrasting colors according to individually understood criteria of similarity, sameness, or distinctness. Moreover, even the choice of specific colors in the spectrum is an individual feature.

It is known that colors have a structure based on three primary colors and their combinations. After all, it is an interesting observation that only the concepts of lightness (white) and darkness (black) are basically universal, and also, if there is one, red color including reds, oranges, as well as yellows, pinks and purples up to filberts. An analysis of color naming in various languages indicates that languages distinguishing six colors have names for the light, dark, red, green, yellow, and blue.

Art perception theory [1] treats shape and color separately. Shape is indicated as a feature that better identifies the object and reveals more numerous qualitative features. Color, on the other hand, depends more on the environment, such as lighting, e.g., strong light makes reds appear brighter, while dim light serves blues and greens.

The basic concepts used in color theory are primary and complementary colors. However, a distinction has to be made between fundamental primary colors, i.e., the pure colors on which the perception of colors is built, and simple generative colors, i.e. the colors needed to gain a wide range of tones in a physical sense.

All color systems assume that a certain small number of tones is enough to obtain a full, or at least a wide color gamut. According to Hering’s color theory [2], humans have sensitivity to the colors black and white, blue and yellow, and green and red. The trichromatic Young-Helmholtz theory [4], on the other hand, assumes the existence of three basic generative colors: red, green, and filbert. Finally, in the 20th century, it was confirmed that pigments on retinal receptors respond to three wavelengths: 447 nm (blue-violet), 540 nm (green), and 577 nm (yellow).

Color theory further indicates that which colors will best form a wide range of colors depends on the method of combination: whether by addition (additive combination) or subtraction (subtractive combination). With additive combining, the eye perceives the sum of the waves (e.g., those emitted by a screen), and with subtractive combining, the impression of color is caused by the remainder left over after light absorption (e.g., stained glass).

To conclude this section, let us recall the concept of complementarity. Generative complementaries are those which, combined, produce monochromatic whites or grays, and fundamental complementaries are which, in perception, desire and complement each other. For example, Helmholz gives as complementary pairs red and blue green, yellow and blue, and green and pink red.

Want to become a part of #espeocrew? Check our current job offers and apply!

from color perception to css

Color models


Historically, RYB is the first color model based on the discoveries of Isaac Newton. The generative colors in this model are red, yellow, and blue. The model was patented in 1719 by Jacob Christoph Le Blon. The RYB model is a subtractive one and was used for printing on white paper. RYB pigments combined together produce black. The colors that are generated by mixing the base pigments include orange (red with yellow), green (yellow with blue), and purple (blue with red).


The RGB model creates a gamut from the primary generative colors: red, green, and blue. Zero intensity of each component defines black, while the full intensity of the generative colors gives white. Equal intensity of all the components produces gray. Color ranges are defined in several ways: from 0 to 1, with any fractional value in between, or as unsigned integers ranging from 0 to 255, (8-bit). High-end digital imaging equipment often uses larger ranges, such as 10, 16, or 24 bits. In practice, for the use on monitors, printers, and the World Wide Web, the sRGB standard created by HP and Microsoft in 1996 is used.


The CMY model uses cyan, magenta, and yellow as the primary generative colors. The colors in the possible palette are obtained by layering the producing colors. When cyan, magenta, and yellow inks are combined, the result (in theory) is black. In practice, however, this combination results in a dark gray or dark brown. Therefore, in practical solutions, the color black is added to this model (CMYK model). It is also possible to achieve the so-called deep black by mixing generative colors and adding black. In this model, the color white is treated as no color (C0 M0 Y0 K0). The colors of the RGB model are obtained by mixing magenta with cyan (blue), magenta with yellow (red), and cyan with yellow (green), respectively.

Furthermore, the generative colors of the CMY model are obtained by combining the corresponding colors of the RGB model: red with green gives yellow, green with blue gives cyan, and blue with red gives magenta.

The RYB, RGB, and CMY models can be graphically described as cubic models: generative colors are placed on the X, Y and Z axes of length 1, and a color is defined as a point with three coordinates. Note that in the above models, it is difficult to define the concepts of color intensity, brightness or saturation. Other models are used for this purpose.


The HSL color model was developed in 1938 by Georges Valensi as a method of adding color coding to existing monochrome transmissions containing only the L signal. The model uses the parameters hue from the RGB model, saturation, and lightness. The angular coordinate starts at red (angle 0°), then passes through green (angle 120°) and blue (angle 240°) before returning to red (angle 360°). The distance from the cylinder axis defines the saturation. The vertical axis is achromatic or gray, ranging from white with a brightness of 1 o black with a brightness of 0. Primary and secondary colors red, yellow, green, cyan, blue, and magenta are arranged around the outer edge of the cylinder with the saturation value of 1. However, in this model, lightness is quite meaningless [3]. Colors can have the same lightness value, with wildly different perceptual lightness.

CIE L*a*b*

The CIE LAB model (also Lab) is a color model defined in 1976 by the International Commission on Illumination (CIE). It expresses color by indicating three values: brightness (L) and a* and b* for the four colors recognized by the eye: red, green, blue, and yellow. CIE L*a*b* was designed to be a perceptually uniform space in which the numerical change corresponds to the corresponding perceived color change. It is used to detect small differences in color.

CIE L*a*b* is a device-independent model of the standard observer. Colors refer to the averaged results of color matching experiments under laboratory conditions. The CIE L*a*b* space is three-dimensional and covers the entire range of color perception. It is based on the model of complementary colors. The brightness value (L) defines black at 0 and white at 100. The a* axis refers to the green-red complementary colors, with values negative toward green and positive toward red. The b* axis represents the blue-yellow complements with negative toward blue and positive toward yellow. CIE L*a*b* is calculated with respect to white. Although the a* and b* axes are unbounded, software implementations often limit these values for practical reasons, such as limiting a* and b* to integers in the range of -128 to 127.


To solve the problem of HSL model lightness, one can use the LCH model. The first argument specifies the CIE Lightness (L), interpreted as Lightness argument of Lab. The second is the chroma, understood as the amount of color, starting a 0 and maximum theoretically unbounded, but practically not exceeding 230. The third argument is the hue angle interpreted similarly to the hue on HSL, with 0° along the positive a* axis (red), 90° pointing along the positive b* axis (yellow), 180° along the negative a* axis (green), and 270° along the negative b* (blue). If the chroma is set to 0%, the hue component can be omitted. If the lightness of an LCH color is 0%, both the hue and chroma components matter.

from color perception to css

Cascading StyleSheet color evolution

Let us now trace the evolution of color support in successive versions of the Cascading Style Sheets (CSS) specifications. The first version of the specification [5] was published in late 1996. Basic CSS support was provided by Internet Explorer 3, but only IE4, which was released in late 1997, correctly supported CSS1. Later implementations, such as in Netscape 4, had numerous bugs, leading it to be thought that CSS itself was flawed. Finally, in 1996, CSS1 was recommended as the standard.


Color in CSS1 [5] is either a keyword or an RGB numeric specification. CSS1 supported 16 colors derived from the Windows VGA palette (aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow). However, their RGB values are not defined. The RGB color model was used in numeric color specifications. The format for hexadecimal RGB values included the # character followed by three or six hexadecimal characters. The three-digit RGB notation #rgb is converted to the six-digit #rrggbb by duplicating digits rather than by adding zeros, such as #abc converts to #aabbcc. The functional notation rgb() is also specified, which gives a comma-separated list of three numeric values in the range 0-255 or three percentage values in the range 0% to 100%. RGB colors are specified in the sRGB color space.


In the next version of the specification [6], the color orange was added to the color list, and numerical values were defined for the colors in the palette:

maroon #800000
red #ff0000
orange #ffA500
yellow #ffff00
olive #808000
purple #800080
fuchsia #ff00ff
white #ffffff
lime #00ff00
green #008000
navy #000080
blue #0000ff
aqua #00ffff
teal #008080
black #000000

In the next version of CSS2.2 released in 2016 [7], the specification remained unchanged.

CSS Color Module 3

Unlike CSS 2, which is a specification that defines a variety of features, CSS3 was broken up into separate documents (modules). The CSS Color Module Level 3 [8], recommended as a valid specification in 2018, has been extracted from the specification.

CSS Color 3 introduces the concept of opacity taking values from 0 (fully transparent) to 1 (fully opaque), and the RGB color model has been extended with an alpha channel to the RGBA model to allow color opacity to be specified. The rgba() function was added to the functional notation to allow the opacity value to be written as the last parameter.

CSS Color 3 extends the color value with the transparent keyword, and allows it to be used in all properties that take a color value. It also extends the color list to the X11COLORS list with the addition of gray variants from SVG 1.0.

CSS Color 3 adds support for the HSL model in addition to numeric RGB colors, and the conversion from HSL to sRGB is purely mathematical. The functional notation hsl() has an equivalent that supports the alpha channel — hsla().

Are you a Front-end Developer looking for new career opportunities? Check out our open job positions and apply!

CSS Color Module Level 4

Subsequent drafts [9] of the CSS Color Module specification extends definitions of color and color space.

Color is understood as a numerical or textual definition of human perception of light or a physical object illuminated by light. The color of an object depends on how much light it reflects at each visible wavelength and the actual color of the light illuminating it, while the color of a light-emitting object such as the colors on a computer screen, depends on the amount of light emitted at each visible wavelength. Color comparisons are made by converting spectra to the CIE XYZ scale — an additive color space with luminance as the Y component.

CSS Color 4 also defines the term color space as the organization of colors with respect to a basic colorimetric model, so that there is a clear, objectively measurable meaning for each color in that color space. It also means that the same color can be expressed in multiple color spaces or transformed from one color space to another and still look the same.

CSS Color 4 also uses the concept of chromaticity as a measure of color in which the brightness component has been subtracted.

CSS Color 4 adds to the already existing color functions rgb(), rgba(), hsl(), hsla() new ones: hwb(), lab(), lch(), oklab(), oklch(), and color(). Of these, hsl(), hsla(), hwb(), lch(), and oklch() are cylindrical polar color representations, specifying color using the hue angle, a central axis representing brightness (black to white), and a radius representing saturation or chromaticity, i.e., how far the color is from neutral gray.

The color() function allows to specify a color in a color space other than sRGB, in which most other functions operate. These include P3, Adobe RGB (1998), ProPhoto RGB, or Rec. 2020.

CSS Color 4 also covers the issue of color interpolation, which occurs in gradients, compositions, filters, transitions, animations, and color mixing and modification functions. It is done by linear interpolation of each component of a calculated color value separately, in a specified color space. In some cases, the result of physically mixing two colored lights is desired. In such a case, the linear CIE XYZ or sRGB color space is appropriate because they are linear in light intensity. However, if the colors must be perceptually uniform (e.g., in a gradient), then it is reasonable to use Lab/OKLab spaces, which are perceptually uniform. To avoid maximizing chromaticity, the use of LCH/OKLCH is recommended, and for compatibility with older web content, the sRGB color space should be chosen.

from color perception to css

CSS Color Module 5

The next draft [10] of the specification adds two new functions: color-mix() and color-contrast().

The first one mixes two colors in the given space in the given proportions. The following algorithm is used: both colors are converted to the required color space, and then the colors are interpolated. If an alpha multiplier was created during percentage normalization, the alpha component of the result is multiplied by the alpha multiplier.

The second function takes as parameters a single color, a list of two or more colors, and, optionally, a target luminance contrast. The single color is separated from the list by the vs keyword, and the target contrast, if any, is separated from the list by the to keyword. The first color that meets or exceeds the target contrast value is then selected from this list. If no target value is specified, the first color with the highest contrast relative to a single color is selected.

Follow us on Instagram for more insights from our experts!

Final remarks

According to MDN [11], CSS Color 3 is rather fully implemented in the modern web browsers. However, the CSS Color 4 and CSS Color 5 recommendations, which are still in development, are implemented partially, e.x., color(), lab(), and lch() functions are available in Safari browser, while color-mix() or color-contrast() are not available at all. 

And while color is a key element of good graphic design, still not all graphic designers’ ideas can be supported in web applications. Despite its rapid development, color in the Web still has a long way to go.

References and further reading

[1] R. Arnheim, Art and Visual Perception. A psychology of the creative eye, California 1974.

[2] E. Hering, Zur Lehre vom Lichtsinn, Vienna 1878.


[4] T. Young, Bakerian Lecture: On the Theory of Light and Colours. Phil. Trans. R. Soc. Lond. (1802) 92, pp.12–48.

[5] Cascading Style Sheets, level 1,

[6] Cascading Style Sheets Level 2 Revision 1,

[7] Cascading Style Sheets Level 2 Revision 2,

[8] CSS Color Module Level 3,

[9] CSS Color Module Level 4,

[10] CSS Color Module Level 5,