CSS Color Module Level 6

Editor’s Draft,

More details about this document
This version:
Latest published version:
CSSWG Issues Repository
Chris Lilley (W3C)
Una Kravets (Google)
Lea Verou (Invited Expert)
Adam Argyle (Google)
Suggest an Edit for this Spec:
GitHub Editor
Delta Spec:
Not Ready For Implementation

This spec is not yet ready for implementation. It exists in this repository to record the ideas and promote discussion.

Before attempting to implement this spec, please contact the CSSWG at www-style@w3.org.


This module extends CSS Color [css-color-5] to add contrast calculation.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.

Status of this document

This is a public copy of the editors’ draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don’t cite this document other than as work in progress.

Please send feedback by filing issues in GitHub (preferred), including the spec code “css-color” in the title, like this: “[css-color] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list www-style@w3.org.

This document is governed by the 2 November 2021 W3C Process Document.

1. Introduction

This section is not normative.

This module adds two one function: color-contrast().

2. Selecting the most contrasting color: the color-contrast() function


In only one current engine.

FirefoxNoneSafari🔰 15+ChromeNone
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

This function takes, firstly, a single color (typically a background, but not necessarily), secondly, a list of two or more colors, and thirdly, an optional target luminance contrast [WCAG21].

It returns the first color in the list to meet or exceed the specified target contrast or, if no target is given, the color in the list with the greatest contrast.

The single color is separated from the list with the keyword vs and the target contrast, if present, is separated from the list with the keyword to.

color-contrast() = color-contrast( <color> vs <color>#{2,}  [ to [<number> | AA | AA-large | AAA | AAA-large]]? )

The keyword AA is equivalent to 4.5, AA-large is equivalent to 3, AAA is equivalent to 7, and AAA-large is equivalent to 4.5 .

2.1. Calculating luminance and WCAG 2.1 contrast

For each color in the list, the CIE Luminance (Y) is calculated, relative to a D65 whitepoint.

For each pair of colors, the WCAG 2.1 contrast is calculated: contrast = (Yl + 0.05) / (Yd + 0.05) where Yd is the luminance of the darker color in the pair and Yl is the luminance of the lighter color. The factor 0.05 represents the luminance contribution of the viewing flare.

Suppose that the single color was
color(display-p3 0.38 0.11 0.05)

while the first color in the list was


The calculation is as follows:

2.2. Finding the winning color

It then selects from that list the first color to meet or exceed the target contrast. If no target is specified, it selects the first color with the highest contrast to the single color.

color-contrast(wheat vs tan, sienna, var(--myAccent), #d2691e)

The calculation is as follows:

Suppose myAccent has the value #b22222:

The highest contrast ratio is 5.081 so var(--myAccent) wins
color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to AA)

The calculation is as follows:

The first color in the list which meets the desired contrast ratio of 4.5 is darkgreen.

color-contrast(wheat vs bisque, darkgoldenrod, olive, sienna, darkgreen, maroon to 5.8)

The calculation is as follows:

The first color in the list which meets the desired contrast ratio of 5.8 is maroon.

The colors in the list (after the keyword vs) are tested sequentially, from left to right; a color is the temporary winner if it has the highest contrast of all those tested so far.

List traversal is terminated once the target contrast has been met or exceeded.

Once the end of the list is reached, if there is no target contrast, the current temporary winner is the overall winner. Thus, if two colors in the list happen to have the same contrast, the earlier in the list wins because the later one has the same contrast, not higher.

If there is a target contrast, and the end of the list is reached without meeting that target, either white or black is returned, whichever has the higher contrast.

color-contrast(wheat vs bisque, darkgoldenrod, olive to AA)

The calculation is as follows:

No color in the list meets the desired contrast ratio of 4.5, so black is returned as the contrast (15.982) is higher than that of white (1.314).

foo {
  --bg: hsl(200 50% 80%);
  --purple-in-hsl: hsl(300 100% 25%);
  color: color-contrast(var(--bg) vs hsl(200 83% 23%), purple, var(--purple-in-hsl));

The calculation is as follows:

The calculated values here are shown to six significant figures, to demonstrate that early rounding to a lower precision would have given the wrong result (0.061575 is very close to 0.061487; 6.08409 is very close to 6.08889).

3. Resolving <color> Values

3.1. Resolving color-contrast() values

If all <color> parameters resolve to the corresponding colors in their respective color spaces, the computed value is the winning color resolved according to CSS Color 4 § 14 Resolving <color> Values. Otherwise (if currentColor was used in the function), the computed value is the color-contrast() function with each <color> parameter resolved according to CSS Color 4 § 14 Resolving <color> Values, and the keywords AA, AA-large, AAA, AAA-large replaced with their corresponding numeric value, thus preserving inheritance into child elements.

For example, given the value
color-contrast(rgb(179 213 230) vs cadetblue, hsl(200 83% 23%) to AA)

the contrast with cadetblue is 1.97 while the contrast with hsl(200 83% 23%) is 6.09 which exceeds 4.5, the value for AA; so it has the computed value of the resolved hsl function:

rgb(10 75 107)

For example, given a current color value of rgb(179 213 230), the value

color-contrast(currentColor vs hsl(200 83% 23%), purple to AA)

has the computed value

color-contrast(currentColor vs rgb(10 75 107), rgb(128 0 128) to 4.5)

4. Serialization

This section extends CSS Color 4 § 15 Serializing <color> Values to add serialization of the results of the color-contrast() function.

In this section, the strings used in the specification and the corresponding characters are as follows.

String Character
" " U+0020 SPACE
"," U+002C COMMA
"." U+002E FULL STOP
"/" U+002F SOLIDUS

The string "." shall be used as a decimal separator, regardless of locale, and there shall be no thousands separator.

As usual, if the alpha of the result is exactly 1, it is omitted from the serialization; an implicit value of 1 (fully opaque) is the default.

4.1. Serializing color-contrast()

The serialization of the result of a color-contrast() function is a <color>, as defined in CSS Color 4 § 15 Serializing <color> Values. The form used is the same as that used to specify the winning color.

The minimum precision for round-tripping is the same as that specified in CSS Color 4 § 15 Serializing <color> Values.

The winner of this contrast choice
color-contrast(wheat vs olive, sienna, maroon)

is maroon, so the result is serialized as "rgb(128 0 0)".

While the winner of

color-contrast(wheat vs color(prophoto-rgb 0.4 0.4 0.2), color(display-p3 0.45 0.08 0.05))

is color(display-p3 0.45 0.08 0.05), so the result is serialized as "color(display-p3 0.45 0.08 0.05)".

5. Security Considerations

No new security considerations have been reported on this specification.

6. Privacy Considerations

No new privacy considerations have been reported on this specification.

7. Accessibility Considerations

This specification introduces a new feature to help stylesheet authors write stylesheets which conform to WCAG 2.1 section 1.4.3 Contrast (Minimum).

8. Changes

8.1. Changes from Colors 5

The new color-contrast() function allows one of a list of colors to be chosen, based on the WCAG 2.1 contrast with a specified color.


Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.


Tests relating to the content of this specification may be documented in “Tests” blocks like this one. Any such block is non-normative.

Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
A CSS style sheet.
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.


Terms defined by this specification

Terms defined by reference


Normative References

CSS Color Module Level 4 URL: https://www.w3.org/TR/css-color-4/
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 4. URL: https://drafts.csswg.org/css-values-4/
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
Andrew Kirkpatrick; et al. Web Content Accessibility Guidelines (WCAG) 2.1. URL: https://w3c.github.io/wcag/21/guidelines/

Informative References

Chris Lilley; et al. CSS Color Module Level 5. URL: https://drafts.csswg.org/css-color-5/