If a status, error or link is shown only in color, some residents cannot use it. Here is how to add a second cue to forms, calendars and charts.
This criterion says color cannot be the only visual way to convey information, indicate an action, prompt a response or distinguish a visual element. The goal is simple: a person who cannot tell red from green, who uses a monochrome display, or who has turned on a forced high-contrast palette should still get the same information.
In practice, a second cue is enough. Text, an icon with a different shape, a pattern, an underline or a border weight all work. A red outline around a field is not wrong; a red outline that is the only sign of an error is.
Color blindness is common, but it is not the only group affected. Someone reading in bright sun, someone printing a page in grayscale and someone whose operating system overrides page colors all lose color information in the same way.
Government and school sites are full of color-coded status: a green dot for an open permit counter, a red day on a park reservation calendar, a colored line on a transit map, a red label on a missing form field. DOJ guidance on web accessibility lists color as the only way to convey information as a common barrier, so this is one of the first things worth checking on a service page.
The pattern is predictable. A designer picks a legend, the legend works for them, and the legend is never tested without color. Pages that carry a payment, an appointment or a deadline are the highest-stakes places to get this wrong, because a missed signal costs the resident something real.
When a vendor supplies status components, ask for the non-color cue in the vendor's component library, not just in your own templates.
A county clinic form that marks required fields with a red label and errors with a red border gives a color-blind visitor nothing to act on. Add words, and tell the field's state to assistive technology.
<label for="dob" style="color:#c62828">Date of birth</label>
<input id="dob" name="dob" style="border:2px solid #c62828"><label for="dob">Date of birth <span>(required)</span></label>
<input id="dob" name="dob" required aria-invalid="true"
aria-describedby="dob-err" style="border:2px solid #b3261e">
<p id="dob-err" class="err">Error: enter your date of birth as MM/DD/YYYY.</p>The error text starts with the word Error so the message makes sense without the red styling. The red border is still there for people who benefit from it.
Links in a paragraph are easy to miss if they differ from the body text only by hue. An underline is the most dependable non-color cue. If you remove it, the link must have at least a 3:1 contrast ratio against the surrounding text and gain another visual cue on hover and focus.
.bill-help a { color: #1a73e8; text-decoration: none; }
/* body text #333, link blue: hue is the only difference */.bill-help a { color: #0a4d8c; text-decoration: underline; }
.bill-help a:hover,
.bill-help a:focus-visible { text-decoration-thickness: 3px; }A park reservation calendar that shades open days green and full days red fails for anyone who cannot tell the shades apart. Put the status in the cell, not only in its fill.
<td class="day open">14</td>
<td class="day full">15</td><td class="day open"><button>14 <span>Open</span></button></td>
<td class="day full">15 <span>Full</span></td>For a line chart or a transit map, label lines directly, or vary line style and end markers. A legend that depends on hue alone leaves the reader guessing. Images of maps that contain color-coded meaning need the same treatment; where a map is only decorative this criterion does not apply.
Mobile screens often show route or ticket status as a colored circle. The pair below keeps the color and adds a symbol and a word.
// SwiftUI
Circle().fill(delayed ? .red : .green)
.frame(width: 12, height: 12)// SwiftUI
Label(delayed ? "Delayed" : "On time",
systemImage: delayed ? "exclamationmark.triangle.fill"
: "checkmark.circle.fill")
.foregroundStyle(delayed ? .red : .green)// Jetpack Compose
Box(Modifier.size(12.dp).background(if (delayed) Color.Red else Color.Green))// Jetpack Compose
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
if (delayed) Icons.Filled.Warning else Icons.Filled.CheckCircle,
contentDescription = null,
tint = if (delayed) Color(0xFFB3261E) else Color(0xFF1B5E20)
)
Spacer(Modifier.width(4.dp))
Text(if (delayed) "Delayed" else "On time")
}Ship it when:
See also common barriers for the other problems that tend to travel with this one.