What to Watch for When Using Red and Green Together in Web UI
Green often signals that something is available, while red suggests a limit or problem. On a website, however, showing “Registration open” in green and “Fully booked” in red may not be enough. Some people find those hues hard to distinguish, and a grayscale screen can make them appear surprisingly similar. Even when both colors contrast well against white, that does not guarantee that the two colors are easy to tell apart. This guide explores what to check when red and green appear together in an interface, using workshop registration cards as an example.
Red and green need more than individually sufficient contrast
The Web Content Accessibility Guidelines (WCAG) 2.2 include the Level A success criterion “Use of Color.” It requires that color not be the only visual way of conveying information or distinguishing a state. If a page relies entirely on the rule “green means you can register, red means you cannot,” visitors unable to distinguish the colors may miss an important distinction. Keep explicit words such as “Registration open” and “Fully booked” visible at all times.
For example, dark green #15803D and red #B91C1C each stand out individually against white #FFFFFF. But the contrast ratio between the green and red themselves is only about 1.29:1. Contrast ratio describes the difference in relative brightness between two colors; it does not directly measure how different their hues look. Do not treat this 1.29:1 as a standalone WCAG pass-or-fail score. It illustrates why a difference in hue should not be the only way to recognize a status.
In a list of nearby cards, you can reinforce the green state with a solid border and the red state with a dashed border. Add a check symbol or exclamation mark if helpful, but retain written labels because symbols can have ambiguous meanings too. Include practical next-step information such as “5 places left; registration is available” or “All places are taken; registration is unavailable.” A visitor should understand what they can do without interpreting a color code.
Example: place open and fully booked workshops side by side
Consider a fictional booking page where a Wednesday workshop still accepts registrations, while a Saturday workshop is fully booked. Use pale blue-gray #F8FAFC outside the cards and white #FFFFFF within them. Workshop names use dark blue-gray #1F2937, with slate #475569 for the supporting availability details. Keeping long text neutral allows the red and green to occupy smaller, more focused areas of the interface.
The open status uses dark-green #166534 text on a pale-green #ECFDF5 badge, with a solid green #15803D card border. The fully booked status uses dark-red #991B1B text on a pale-red #FEF2F2 badge, with a dashed red #B91C1C border. Both cards use the same underlined blue #1D4ED8 details link. That link color has a consistent meaning: it identifies a destination, not whether registration is possible.
<section class="event-status-list" aria-label="Workshop availability">
<article class="event-status event-status--open">
<h3>Wednesday design workshop</h3>
<p class="event-status__badge">
<span aria-hidden="true">✓</span><strong>Registration open</strong>
</p>
<p class="event-status__details">5 places left. Registration is available.</p>
<a href="/events/wednesday/">View Wednesday workshop details</a>
</article>
<article class="event-status event-status--full">
<h3>Saturday design workshop</h3>
<p class="event-status__badge">
<span aria-hidden="true">!</span><strong>Fully booked</strong>
</p>
<p class="event-status__details">
All places are taken. Registration is unavailable.
</p>
<a href="/events/saturday/">View Saturday workshop details</a>
</article>
</section>
.event-status-list {
display: grid;
gap: 18px;
padding: 20px;
background-color: #F8FAFC;
}
.event-status {
padding: 20px;
border: 3px solid;
border-radius: 12px;
background-color: #FFFFFF;
color: #1F2937;
}
.event-status h3 { margin: 0 0 12px; }
.event-status--open {
border-color: #15803D;
border-style: solid;
}
.event-status--full {
border-color: #B91C1C;
border-style: dashed;
}
.event-status__badge {
display: inline-flex;
gap: 8px;
align-items: center;
margin: 0;
padding: 6px 12px;
border-radius: 8px;
}
.event-status--open .event-status__badge {
background-color: #ECFDF5;
color: #166534;
}
.event-status--full .event-status__badge {
background-color: #FEF2F2;
color: #991B1B;
}
.event-status__details { color: #475569; }
.event-status a {
color: #1D4ED8;
text-decoration: underline;
text-underline-offset: 3px;
}
.event-status a:focus-visible {
outline: 3px solid #1D4ED8;
outline-offset: 3px;
}
The HTML (HyperText Markup Language, which describes webpage content and structure) includes the status words and explanations from the start. The check and exclamation symbols have aria-hidden="true", since the adjacent words already provide the essential status for screen readers and other assistive technology. The :focus-visible CSS (Cascading Style Sheets) selector adds a blue outline when a visitor reaches a details link using keyboard navigation. The /events/wednesday/ and /events/saturday/ URLs are placeholders to replace with real destinations. This example does not implement registration or booking actions.
Check text contrast and red-green distinguishability separately
Against a white card #FFFFFF, the dark heading color #1F2937 measures approximately 14.68:1 and supporting slate text #475569 measures 7.58:1. The open badge’s dark green #166534 against pale green #ECFDF5 reaches about 6.77:1; the fully booked badge’s dark red #991B1B against pale red #FEF2F2 reaches about 7.60:1. These combinations exceed the 4.5:1 generally required for normal-sized text under WCAG 2.2 Level AA.
The solid green border #15803D measures approximately 5.02:1 against white, while the dashed red border #B91C1C reaches about 6.47:1. Against the outer pale-blue-gray surface #F8FAFC, the border ratios are about 4.79:1 and 6.18:1 respectively. The blue details link #1D4ED8 against white reaches about 6.70:1, and the same blue focus outline against the pale surrounding surface measures about 6.41:1. For visual information necessary to identify controls or states, WCAG 2.2 generally specifies at least 3:1 non-text contrast with adjacent colors. Here the red and green borders are not directly adjacent, so their mutual 1.29:1 is not itself the applicable non-text contrast pass/fail measurement.
Before publishing, view the cards in grayscale and confirm that the solid versus dashed border, written status, and availability explanation remain clear. A color-vision simulator can supplement that review, but cannot guarantee legibility for every visitor; also check narrow screens and enlarged text. If availability changes dynamically in a real application, update the visible words along with the colors and consider how to communicate the change to assistive technology. The contrast figures here describe specified color pairs, not a guarantee of overall accessibility or real-world perception.
HueRoll can help explore potential colors and compare a selected color against white or black. It does not automatically evaluate arbitrary red-green pairs or certify WCAG conformance. Once colors are selected, verify the pairs that actually touch in the finished interface and confirm that its text and border patterns communicate the same information without color.