Description
Product
axe-core
Product Version
4.8.2
Latest Version
- I have tested the issue with the latest version of the product
Issue Description
Expectation
We saw an example today of a customer site using a text input that used event handlers to apply different classes to the input element in empty vs nonempty states. The empty state used a color
with < 4.5:1 contrast, but the non-empty state was fine. This shouldn't be a color contrast violation.
Actual
This caused a color-contrast
false positive because axe-core
evaluates the text input contrast styling even when it contains no text:
axe-core/lib/rules/color-contrast-matches.js
Lines 71 to 72 in f1af598
This gives extra-confusing results when the text input uses a placeholder
- the contrast rule will currently ignore the placeholder text styling and instead evaluate as if the input contained a non-placeholder value, and any resulting violations will appear as if it's evaluated the placeholder text with a usually-incorrect foreground color.
Placeholder text is generally subject to contrast requirements, so ideally we'd evaluate the placeholder (but using its foreground color, not the input's). But that can be a separate issue vs this false positive; for the purposes of this bug, either of "incomplete" or "not matched" would be an improvement over the current behavior.
How to Reproduce
Suggested new color-contrast.html
integration test cases:
<!-- currently fails, should be either incomplete (with some new message format suggesting testing it with a value set) or unmatched -->
<input
id="ignore13"
type="text"
style="background: #fff; color: #eee"
/>
<!-- currently fails, should be either pass (ideal eventually), incomplete (ideal for this bug), or unmatched (better than false positive at least) -->
<style>
.placeholder-000::placeholder {
color: #000
}
</style>
<input
id="tbd"
type="text"
placeholder="Placeholder"
style="background: #fff; color: #eee"
class="placeholder-000"
/>
<!-- currently fails, but against #eee foreground color. Should either fail with #ddd foreground color data (ideal eventually), incomplete (ideal for this bug), or unmatched (false negative, but better than the above case being a false positive) -->
<style>
.placeholder-ddd::placeholder {
color: #ddd
}
</style>
<input
id="tbd"
type="text"
placeholder="Placeholder"
style="background: #fff; color: #eee"
class="placeholder-ddd"
/>
Additional context
The "match text inputs without text" behavior appears to have been introduced a few years ago in #2130. The comment at the relevant line in color-contrast-matches
suggests that it was done intentionally, but I didn't see a good explanation of why the intention was there in the PR or in the motivating issue