From e59859d313cc4c86069488565e32f67a2dd3da03 Mon Sep 17 00:00:00 2001 From: Lea Verou Date: Thu, 20 Oct 2022 15:39:14 -0400 Subject: [PATCH] [css-color-6] contrast-color() algorithm syntax changes - If color candidates are provided, algorithm is mandatory, otherwise a UA dependent algorithm is used (part of the resolution in #7361 ) - Reorganization of prose and examples - Add keyword to specify algorithm without target contrast Co-Authored-By: fantasai <725717+fantasai@users.noreply.github.com> --- css-color-6/Overview.bs | 235 ++++++++++++++++++++++------------------ 1 file changed, 127 insertions(+), 108 deletions(-) diff --git a/css-color-6/Overview.bs b/css-color-6/Overview.bs index 2ad98ee83913..616d25ca29af 100644 --- a/css-color-6/Overview.bs +++ b/css-color-6/Overview.bs @@ -34,7 +34,7 @@ Introduction {#intro} This section is not normative. - This module adds two one function: + This module adds a new <> function: ''contrast-color()''. @@ -52,88 +52,44 @@ Introduction {#intro} https://caniuse.com/mdn-css_types_color_color-contrast --> -Computing a sufficiently contrasting color: the ''contrast-color()'' function {#colorcontrast} +Computing a Contrasting Color: the ''contrast-color()'' function {#colorcontrast} ======================================================================================== - The purpose of this function is to generate sufficiently contrasting colors from other colors, - without authors having to compute them manually. + The contrast-color() [=functional notation=] + identifies a sufficiently contrasting color + against a specified background or foreground color + without requiring manual computation. Its syntax is:
-		contrast-color() = contrast-color( <> [ vs <>#{2,} ]? [ to <>]? )
-		<> = wcag2([<> | [ aa | aaa ] && large? ])
+		<> = contrast-color( <> [[ vs <># ]? to <>]? )
+		<> = <>
 	
- The only mandatory argument is the first color, which is the color to be contrasted, - typically (but not necessarily) a background color. + The only mandatory argument is the base color + against which the contrast is computed. + This is typically (but not necessarily) a background color. - An optional list of color candidates is provided after a ''vs'' keyword. + An optional list of contrast color candidates may be provided after a ''vs'' keyword. If no candidates are provided, the default candidates are used: ''white, black''. - An optional target luminance contrast [[!WCAG21]] - is provided after a ''contrast-color()/to'' keyword. + The <> argument specifies the contrast algorithm to use. + If no [=color candidates=] have been provided, + <> may be omitted, + in which case a UA-chosen algorithm is used. + Arguments to a <> [=functional notation=] + indicate the target contrast level. - If a target contrast is specified, - the returned color is the first color candidate that meets or exceeds the target contrast. - If no target is given, + If the [=target contrast level=] is omitted, the color candidate with the greatest contrast is returned. - If multiple candidates have the same contrast, - the one that comes earliest in the list is returned. + Otherwise, + the returned color is the first color candidate that meets or exceeds that level, + defaulting to ''white'' or ''black'' if none qualify. - 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. - The target contrast is specified by providing a function for the algorithm used - (currently only [WCAG 2.1](#luminance-contrast) is supported ) - with the contrast ratio as the argument. - - For ''wcag2()'', ''aa'' is equivalent to ''4.5'', - ''aa large'' (or ''large aa'') is equivalent to ''3'', - ''aaa'' is equivalent to ''7'', - and ''aaa large'' (or ''large aaa'') is equivalent to ''4.5''. - -

- 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 - -
yellow
- - The calculation is as follows: - * color(display-p3 0.38 0.11 0.05) is color(xyz 0.06191 0.03568 0.00463) so the relative luminance is 0.03568 - * yellow is rgb(100% 100% 0%) which is color(xyz 0.76998 0.92781 0.13853) so the relative luminance is 0.92781 - * the contrast is (0.92781 + 0.05) / (0.03568 + 0.05) = 11.4123 -
- -

- 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. +

+Finding the Winning Color

-
-
contrast-color(wheat vs tan, sienna, var(--myAccent), #d2691e)
- - The calculation is as follows: - * wheat (#f5deb3), the background, has relative luminance 0.749 - * tan (#d2b48c) has relative luminance 0.482 and contrast ratio 1.501 - * sienna (#a0522d) has relative luminance 0.137 and contrast ratio 4.273 - - Suppose myAccent has the value #b22222: - * #b22222 has relative luminance 0.107 and contrast ratio 5.081 - * #d2691e has relative luminance 0.305 and contrast ratio 2.249 - The highest contrast ratio is 5.081 so var(--myAccent) wins +

+If there is a target contrast

-
+ Candidate colors are tested sequentially, + starting with the first color in the list, + and ending with an automatically appended ''white, black''. + The first color to pass the specified level of contrast + against the [=base color=] wins. +

+ Contrast algorithms +

+ + ISSUE: Currently only [[#luminance-contrast|WCAG 2.1]] is supported, + however this algorithm is known to have problems, + particularly on dark backgrounds. + Future revisions of this module will likely introduce additional contrast algorithms. + +

+ WCAG 2.1: the ''wcag2'' keyword and ''wcag2()'' function +

+ + The wcag2 keyword and wcag2() [=functional notations=] + indicate use of the [[!WCAG21]] luminance contrast algorithm. + Their syntax is: + +
+	  <> =  wcag | wcag2([<> | [ aa | aaa ] && large? ])
+	
+ + Its [=target contrast level=] keywords map as follows: + * ''aa'' computes to ''4.5'' + * ''aa large'' (or ''large aa'') computes to ''3'' + * ''aaa'' computes to ''7'' + * ''aaa large'' (or ''large aaa'') computes to ''4.5'' + + To find the contrast of a pair of colors, + first their CIE Luminance (Y) is calculated relative to a [=D65 whitepoint=]. + Then 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 [=base color=] were + +
color(display-p3 0.38 0.11 0.05)
+ + while the first [=candidate color=] in the list were + +
yellow
+ + The calculation is as follows: + * color(display-p3 0.38 0.11 0.05) is color(xyz 0.06191 0.03568 0.00463) so the relative luminance is 0.03568 + * yellow is rgb(100% 100% 0%) which is color(xyz 0.76998 0.92781 0.13853) so the relative luminance is 0.92781 + * the contrast is (0.92781 + 0.05) / (0.03568 + 0.05) = 11.4123 +
+ + + + + + + + + + + + +