-
Notifications
You must be signed in to change notification settings - Fork 75
New rule: Text nodes have minimal contrast #833
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7f2571d
c44f9a7
2ef5fb9
a575e29
9aedf12
c5e79d2
5ef8422
28740ca
8e05cfe
83161d2
4877a49
174c64e
28ff7c0
ec8738c
a774d59
5fded85
e093e30
4bae23b
69c25bd
67166e2
c7ce2db
842ee3a
1e2d780
b5fd606
148f535
626b2e7
7e7f242
61173bd
6e7dd05
b8f7651
3ea9cd8
dca1663
c2228d1
8b4c6c4
621e77d
3b3279c
6a8e0cc
8834e9f
1de24e0
a6fd54b
952b11d
00cea78
98d663c
4aebbfa
b9d354a
805875e
43de19e
d993248
8b639d7
243deec
b688d96
4893c3c
2bc7f23
e6fc156
b6b70b0
14b9ecb
3bcd16a
6ba646d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,9 @@ | |
- EARL10-Schema | ||
- labelable | ||
- merchantability | ||
- 14pt | ||
- 18pt | ||
- Helvetica | ||
|
||
# Notes and acronyms | ||
- TODO | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,388 @@ | ||
--- | ||
id: afw4f7 | ||
name: Text has minimum contrast | ||
rule_type: atomic | ||
|
||
description: | | ||
This rule checks that the highest possible contrast of every text character with its background meets the minimal contrast requirement | ||
|
||
accessibility_requirements: | ||
wcag20:1.4.3: # Contrast (Minimum) | ||
forConformance: true | ||
failed: not satisfied | ||
passed: further testing needed | ||
inapplicable: further testing needed | ||
wcag20:1.4.6: # Contrast (Enhanced) | ||
forConformance: true | ||
failed: not satisfied | ||
passed: further testing needed | ||
inapplicable: further testing needed | ||
|
||
input_aspects: | ||
- DOM Tree | ||
- CSS Styling | ||
- Language | ||
|
||
acknowledgements: | ||
authors: | ||
- Brian Bors | ||
- Kasper Isager | ||
- Wilco Fiers | ||
--- | ||
|
||
## Applicability | ||
|
||
Any [visible][] character in a [text node][] that is a [child](https://dom.spec.whatwg.org/#concept-tree-child) (in the [flat tree](https://drafts.csswg.org/css-scoping/#flat-tree)) of an HTML element, except if the [text node][] is a [descendant](https://dom.spec.whatwg.org/#concept-shadow-including-descendant) of an element that: | ||
|
||
- has a [semantic role](#semantic-role) that inherits from [widget](https://www.w3.org/TR/wai-aria-1.1/#widget); or | ||
- is used in the [accessible name](#accessible-name) of a [widget](https://www.w3.org/TR/wai-aria-1.1/#widget) that is [disabled][]; or | ||
- has a [semantic role](#semantic-role) of [group](https://www.w3.org/TR/wai-aria-1.1/#group) and is [disabled][]. | ||
|
||
**Note**: When the [foreground color](#foreground-colors-of-text) is the same as the [background color](#background-colors-of-text), this rule deems the character not [visible][], so it does not need to be tested for contrast. | ||
|
||
## Expectation | ||
|
||
For each test target, the [highest possible contrast](#highest-possible-contrast) between the [foreground colors](#foreground-colors-of-text) and [background colors](#background-colors-of-text) is at least 4.5:1 or 3.0:1 for [larger scale text](#large-scale-text), except if the test target is part of a [text node][] that is [decorative](#decorative), or does not express anything in [human language](https://www.w3.org/TR/WCAG21/#dfn-human-language-s). | ||
|
||
**Note**: Passing this rule does not mean that the text has sufficient color contrast. If all background pixels have a low contrast with all foreground pixels, the success criterion is guaranteed to not be satisfied. When some pixels have sufficient contrast, and others do not, legibility should be considered. There is no clear method for determining legibility, which is why this is out of scope for this rule. | ||
|
||
**Note**: When the text color or background color is not specified in the web page, colors from other [origins](https://www.w3.org/TR/css3-cascade/#cascading-origins) will be used. Testers must ensure colors are not effected by styles from a [user origin](https://www.w3.org/TR/css3-cascade/#cascade-origin-user). Contrast issues cause by specifying the text color but not the background or vise versa, must be tested separately from this rule. | ||
|
||
## Assumptions | ||
|
||
- [Success criterion 1.4.3: Contrast (Minimum)](https://www.w3.org/TR/WCAG21/#contrast-minimum) has exceptions for "incidental" text, which includes inactive user interface components and decorative texts. The rule assumes that [text nodes](https://dom.spec.whatwg.org/#text) that should be ignored are [disabled]() or hidden from assistive technologies. If this isn't the case, the rule may produce incorrect results. | ||
|
||
- [Success criterion 1.4.3: Contrast (Minimum)](https://www.w3.org/TR/WCAG21/#contrast-minimum) also has an exception for logos and brand names. Since logos and brand names are usually displayed through images to ensure correct rendering, this rule does not take logos or brand names into consideration. If a logo or brand name is included using [text nodes](https://dom.spec.whatwg.org/#text), this rule may produce incorrect results. | ||
|
||
- Text that has the same foreground and background color (a contrast ratio of 1:1) is not considered to be "visual presentation of text", making it inapplicable to the success criterion. Text hidden in this way can still cause accessibility issues under other success criteria, depending on the content. | ||
Jym77 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Accessibility Support | ||
|
||
Different browsers have different levels of support for CSS. This can cause contrast issues in one browser that do not appear in another. Because of that, this rule can produce different results depending on the browser that is used. For example, a text that is positioned using CSS transform may be on a different background in a browser that does not support CSS transform. | ||
|
||
## Background | ||
|
||
- [Understanding Success Criterion 1.4.3: Contrast (Minimum)](https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html) | ||
WilcoFiers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
- [Understanding Success Criterion 1.4.6: Contrast (Enhanced)](https://www.w3.org/WAI/WCAG21/Understanding/contrast-enhanced.html) | ||
- [G18: Ensuring that a contrast ratio of at least 4.5:1 exists between text (and images of text) and background behind the text](https://www.w3.org/WAI/WCAG21/Techniques/general/G18) | ||
- [G145: Ensuring that a contrast ratio of at least 3:1 exists between text (and images of text) and background behind the text](https://www.w3.org/WAI/WCAG21/Techniques/general/G145) | ||
- [F83: Failure of Success Criterion 1.4.3 and 1.4.6 due to using background images that do not provide sufficient contrast with foreground text (or images of text)](https://www.w3.org/WAI/WCAG21/Techniques/failures/F83) | ||
- [CSS Scoping Module Level 1 (Editor's Draft)](https://drafts.csswg.org/css-scoping/) | ||
|
||
## Test Cases | ||
|
||
### Passed | ||
|
||
#### Passed Example 1 | ||
|
||
This dark gray text has a contrast ratio of 12.6:1 on the white background. | ||
|
||
```html | ||
<p style="color: #333; background: #FFF;"> | ||
Some text in a human language | ||
Jym77 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
</p> | ||
``` | ||
|
||
#### Passed Example 2 | ||
|
||
This dark gray text has a contrast ratio between 12.6:1 and 5:1 on the white to blue gradient background. | ||
|
||
```html | ||
<p style="color: #333; background: linear-gradient(to right, #FFF, #00F); width: 500px;"> | ||
Some text in a human language | ||
</p> | ||
``` | ||
|
||
#### Passed Example 3 | ||
|
||
This light gray text has a contrast ratio between 13:1 and 5:1 on the background image. | ||
|
||
```html | ||
<p | ||
style="color: #CCC; height:50px; padding-top:15px; background: #000 no-repeat -20px -20px url('../test-assets/contrast/black-hole.jpeg');" | ||
> | ||
Black hole sun | ||
</p> | ||
``` | ||
|
||
#### Passed Example 4 | ||
|
||
This black text has a contrast ratio between 6.1:1 and 9:1 on gray background with white text shadow on it. | ||
|
||
```html | ||
<p style="color: #000; background: #737373; text-shadow: white 0 0 3px"> | ||
Some text in a human language | ||
</p> | ||
``` | ||
|
||
#### Passed Example 5 | ||
|
||
This 18pt large black text has a contrast ratio of 3.6:1 on the gray background. | ||
|
||
```html | ||
<p style="color: #000; font-size:18pt; background: #666;"> | ||
Some text in a human language | ||
</p> | ||
``` | ||
|
||
#### Passed Example 6 | ||
|
||
This 14pt bold black text has a contrast ratio of 3.6:1 on the gray background. | ||
|
||
```html | ||
<p style="color: #000; font-size:14pt; font-weight:700; background: #666;"> | ||
Some text in English | ||
</p> | ||
``` | ||
|
||
#### Passed Example 7 | ||
|
||
The first `p` element is has a contrast ratio of 21:1 (default black on white). The second `p` element contains Helvetica text which is decorative, because it does not convey information or provides functionality; its purpose is to show the aesthetic of the Helvetica font. | ||
|
||
**Note**: Because this is non-text content, [success criterion 1.4.11 Non-text Contrast](https://www.w3.org/TR/WCAG21/#non-text-contrast) requires font example to have a color contrast of 3:1. | ||
|
||
```html | ||
<p style="color: #333; background: #FFF;"> | ||
Helvetica is a widely used sans-serif typeface developed in 1957 by Max Miedinger and Eduard Hoffmann. | ||
</p> | ||
<p style="font-family: helvetica; background: #EEE; color: #777;" aria-hidden="true"> | ||
The quick brown fox jumps over the lazy dog. | ||
</p> | ||
``` | ||
|
||
#### Passed Example 8 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is Passed Example 8 intended to be an example of something non-meaningful or decorative? If so, should it not be an Inapplicable Example? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is an exception mentioned in the expectation. This is because "decorative" is subjective, and the ACT rules format requires the applicability to be objective. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So passed example 7 is including text that can be considered decorative (visual only), and passed example 8 is including text that is not conveying meaning. And in this instance the exceptions are passing examples rather than inapplicable examples because ... ? The only reason I can determine is because the exception is in the expectation rather than the applicability. Is this consistent across rules? Should it be added to the rule guidance docs? Cause in my understanding, a rule is inapplicable to something that is an exception. |
||
This text does not convey anything in human language. | ||
|
||
```html | ||
<p style="color: #000; background: #666;"> | ||
----=====++++++++___________***********%%%%%%%%%%%±±±±@@@@@@@@ | ||
</p> | ||
``` | ||
|
||
#### Passed Example 9 | ||
|
||
This text has the default browser text color on the default browser background color. By default this is black text on a white background, which has a contrast ratio of 21:1. | ||
|
||
```html | ||
<p>Some text in a human language</p> | ||
``` | ||
|
||
#### Passed Example 10 | ||
|
||
This dark gray text has a contrast ratio of 12.6:1 on the white background in a shadow DOM tree. | ||
|
||
```html | ||
<p style="color: #CCC; background: #fff;" id="p"></p> | ||
<script> | ||
const shadowRoot = document.getElementById('p').attachShadow({ mode: 'open' }) | ||
shadowRoot.textContent = '<span style="color: #333;">Some text in English</span>' | ||
</script> | ||
``` | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking at the Expectation, there seems to be missing a Passed Example with decorative text. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Passed example 7 has decorative text. We'll update the example description to make this clearer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree. I think that the text in Passed Example 7 (the font example) does not meet the WCAG definition of "pure decoration" that is the exception to the SC:
The text in that example has the functionality of showing the font. This interpretation (it is not pure decoration) is seconded by the note on that example saying that it needs a 3:1 contrast to meet 1.4.11. I agree that it qualifies as a "Graphical Object" for 1.4.11:
In any case, if the text in that example is "pure decoration", the note and the reference to 1.4.11 need to go away. If it is not "pure decoration" (which I think), then a "pure decoration" example should be added. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "functionality" as it is used in WCAG refers to things users can do on the page. Adding an item to a shopping cart is functionality. See the definition of functionality. The font shape isn't "information" either, otherwise 1.3.1 would apply, information conveyed through presentation. Additionally, if this wasn't "purely decorative", it wouldn't be exempt under the 1.4.3 "incidental" bullet at all. Here's what 1.4.3's understanding doc says about it:
This is precisely the same here. You can change the words without changing the meaning. That makes it decorative. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree that the text is decorative. This is not important enough to block that PR… There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Passed Example 7 is a little confusing. The first paragraph passes because it is using browser default styles. If the second paragraph is decorative, then it is an example of inapplicable. Not sure how to split it as an example though. Perhaps a different example of each is needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll put a foreground and background color on passed example 7 to clear this up, and add a separate example for browser defaults. That's a good point. |
||
### Failed | ||
|
||
#### Failed Example 1 | ||
|
||
This light gray text has a contrast ratio of 2.3:1 on the white background. | ||
|
||
```html | ||
<p style="color: #AAA; background: white;"> | ||
Some text in English | ||
</p> | ||
``` | ||
|
||
#### Failed Example 2 | ||
|
||
This light gray text has a contrast ratio between 1.2:1 and 2.3:1 on the white to blue gradient background. | ||
|
||
```html | ||
<p style="color: #AAA; background: linear-gradient(to right, #FFF, #00F); width: 300px"> | ||
Some text in English | ||
</p> | ||
``` | ||
|
||
#### Failed Example 3 | ||
|
||
This light gray text has a contrast ratio between 2.7:1 and 3:1 on the background image. | ||
|
||
```html | ||
<p | ||
style="color: #555; height:50px; padding-top:20px; background: black no-repeat -20px -20px url('../test-assets/contrast/black-hole.jpeg');" | ||
> | ||
Black hole sun | ||
</p> | ||
``` | ||
|
||
#### Failed Example 4 | ||
|
||
This black text with 30% alpha channel has a contrast ratio of 2.1:1 on the white background. | ||
|
||
```html | ||
<p style="color: rgba(0,0,0,.3); background: #FFF"> | ||
Some text in English | ||
</p> | ||
``` | ||
|
||
#### Failed Example 5 | ||
|
||
This black text with 30% opacity has a contrast ratio of 2.1:1 on the white background. | ||
|
||
```html | ||
<div style="background: #FFF"> | ||
<p style="color: #000; opacity: .3"> | ||
Some text in English | ||
</p> | ||
</div> | ||
``` | ||
|
||
#### Failed Example 6 | ||
|
||
This light gray text has a contrast ratio of 2.3:1 on the white background in a shadow DOM tree. | ||
|
||
```html | ||
<p style="color: #aaa; background: #fff;" id="p"></p> | ||
<script> | ||
const shadowRoot = document.getElementById('p').attachShadow({ mode: 'open' }) | ||
shadowRoot.textContent = 'Some text in English' | ||
</script> | ||
``` | ||
|
||
#### Failed Example 7 | ||
|
||
This semi-transparent gray text has a contrast ratio between 2.3:1 and 4.2:1 on the black and white background. The light gray text is compared to the white section of the background and the dark gray text is compared to the black section of the background. | ||
|
||
```html | ||
<style> | ||
#backgroundSplit { | ||
color: rgba(90, 90, 90, 0.8); | ||
background-position: top 0 left 0; | ||
background-image: linear-gradient(90deg, transparent, transparent 3.3em, black 3.3em, black 6em); | ||
padding: 0 1em; | ||
} | ||
</style> | ||
<span id="backgroundSplit"> | ||
Hello world | ||
</span> | ||
``` | ||
|
||
### Inapplicable | ||
|
||
#### Inapplicable Example 1 | ||
|
||
This text is not [visible][] because of `display: none`. | ||
|
||
```html | ||
<p style="display: none">Some invisible text in English</p> | ||
``` | ||
|
||
#### Inapplicable Example 2 | ||
|
||
This text is not [visible][] because it is positioned off screen. | ||
|
||
```html | ||
<p style="position:absolute; top: -999em">Some invisible text in English</p> | ||
``` | ||
|
||
#### Inapplicable Example 3 | ||
|
||
This text is not [visible][] because the foreground color is the same as the background color. | ||
WilcoFiers marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```html | ||
<p style="color: white; background: white;" aria-hidden="true">Hidden text - U U D D L R L R B A S</p> | ||
``` | ||
|
||
#### Inapplicable Example 4 | ||
|
||
This text is not the child of an HTML element. | ||
|
||
```html | ||
<svg> | ||
<text x="0" y="15">I love SVG!</text> | ||
</svg> | ||
``` | ||
|
||
#### Inapplicable Example 5 | ||
|
||
This text not part of a [text node][]. | ||
|
||
```html | ||
<p> | ||
<img scr="../test-assets/contrast/example.png" alt="example" /> | ||
</p> | ||
``` | ||
|
||
#### Inapplicable Example 6 | ||
|
||
This text is part of a widget because it is a child of a `button` element. | ||
|
||
```html | ||
<button>My button!</button> | ||
``` | ||
|
||
#### Inapplicable Example 7 | ||
|
||
This text is part of a widget because it is a child of an element with the `role` attribute set to `button`. | ||
|
||
```html | ||
<div role="button">My button!</div> | ||
``` | ||
|
||
#### Inapplicable Example 8 | ||
|
||
This text is part of a label of a [disabled][] widget, because it is in a `label` element that is the label for an `input` element with `type="text"`. | ||
|
||
```html | ||
<label style="color:#888; background: white;"> | ||
My name | ||
<input type="text" disabled /> | ||
</label> | ||
``` | ||
|
||
#### Inapplicable Example 9 | ||
|
||
This text is part of a label of a [disabled][] widget, because it is in an element that is referenced by `aria-labelledby` from an element with `role="textbox"`. | ||
|
||
```html | ||
<label id="my_pets_name" style="color:#888; background: white;"> | ||
My pet's name | ||
</label> | ||
<div | ||
role="textbox" | ||
aria-labelledby="my_pets_name" | ||
aria-disabled="true" | ||
style="height:20px; width:100px; border:1px solid black;" | ||
> | ||
test | ||
</div> | ||
``` | ||
|
||
#### Inapplicable Example 10 | ||
|
||
This text is part of a label of a [disabled][] widget, because it is in a `label` element that is the label for an `input` element in a `fieldset` element with the `disabled` attribute. | ||
|
||
```html | ||
<fieldset disabled style="color:#888; background: white;"> | ||
<label> | ||
My name | ||
<input /> | ||
</label> | ||
</fieldset> | ||
``` | ||
|
||
#### Inapplicable Example 11 | ||
|
||
This text is part of a label of a [disabled][] widget, because it is in a `label` element that is the label for an `input` element in an element with `role="group"` with the `aria-disabled="true"` attribute. | ||
|
||
```html | ||
<div role="group" aria-disabled="true" style="color:#888; background: white;"> | ||
<label> | ||
My name | ||
<input /> | ||
</label> | ||
</div> | ||
``` | ||
|
||
[disabled]: #disabled-element 'Definition of disabled' | ||
[visible]: #visible 'Definition of visible' | ||
[text node]: https://dom.spec.whatwg.org/#text 'Definition of text node' |
Uh oh!
There was an error while loading. Please reload this page.