color-contrast — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited color-contrast (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Canonical source:examples/COLOR_CONTRAST_ACCESSIBILITY_BEST_PRACTICES.mdinmgifford/ACCESSIBILITY.mdThis skill is derived from that file. When in doubt, the example is authoritative.
Apply these rules whenever implementing or reviewing colour choices in HTML, CSS, SVG, or any visual interface element.
Sufficient contrast between foreground and background colors is a prerequisite for users to read text, identify UI components, perceive graphical content, and track keyboard focus. Color alone must never be the sole means of conveying information.
All visual interface elements that convey information or require user interaction must meet WCAG 2.2 Level AA contrast thresholds in light mode, dark mode, and forced-colors (high contrast) mode.
| Level | Meaning |
|---|---|
| Critical | Contrast failure makes content or interaction completely inaccessible |
| Serious | Contrast failure significantly impairs access for a disability group |
| Moderate | Contrast issue degrades usability but content remains partially accessible |
| Minor | Best-practice gap; marginal impact |
Normal text and images of text must meet these minimums:
| Text type | Minimum (AA) | Enhanced (AAA) |
|---|---|---|
| Normal text (below 18pt / 14pt bold) | 4.5:1 | 7:1 |
| Large text (18pt+ or 14pt+ bold) | 3:1 | 4.5:1 |
| Logotypes / purely decorative text | Exempt | Exempt |
| Disabled controls | Exempt | Exempt |
"Large text" means 18pt (≈ 24 CSS px) or larger in regular weight, or 14pt (≈ 18.67 CSS px) or larger in bold weight.
:root {
--color-text: #1a1a1a; /* contrast vs #fff: 16.75:1 ✓ */
--color-text-muted: #595959; /* contrast vs #fff: 7.0:1 ✓ */
--color-heading: #333333; /* contrast vs #fff: 12.63:1 ✓ */
--color-link: #0066cc; /* contrast vs #fff: 4.52:1 ✓ */
--color-background: #ffffff;
}
@media (prefers-color-scheme: dark) {
:root {
--color-text: #e8e8e8; /* contrast vs #1a1a1a: 13.61:1 ✓ */
--color-text-muted: #b0b0b0; /* contrast vs #1a1a1a: 7.0:1 ✓ */
--color-link: #66aaff; /* contrast vs #1a1a1a: 5.74:1 ✓ */
--color-background: #1a1a1a;
}
}/* Bad — 2.4:1 contrast, fails 1.4.3 */
.placeholder { color: #aaaaaa; }
/* Bad — informative text in low-contrast colour */
.note { color: #888; } /* fails against white background */UI components and graphical objects required to understand or operate the interface must have 3:1 contrast against adjacent colours.
/* Checkbox border must contrast 3:1 against its background */
input[type="checkbox"] {
--checkbox-border: #767676; /* 4.54:1 against #fff ✓ */
appearance: none;
width: 1.25rem;
height: 1.25rem;
border: 2px solid var(--checkbox-border);
border-radius: 3px;
}Color alone must not be the sole means of conveying information, indicating an action, prompting a response, or distinguishing a visual element. A second, non-color cue must always accompany color.
<!-- Bad: required field indicated only by red label color -->
<label style="color: red;">Email address</label>
<input type="email">
<!-- Bad: error state communicated only by red border -->
<input type="email" style="border-color: red;"><!-- Good: required field — asterisk + color + screen-reader text -->
<label>
Email address
<span aria-hidden="true" class="required-marker">*</span>
<span class="sr-only">(required)</span>
</label>
<input type="email" aria-required="true">
<!-- Good: error state — icon + text + color + aria-invalid -->
<div class="field field--error">
<label for="email">Email address</label>
<input id="email" type="email"
aria-describedby="email-error" aria-invalid="true">
<p id="email-error" class="error-message">
<svg role="img" aria-label="Error" aria-hidden="true">
<use href="#icon-exclamation"></use>
</svg>
Please enter a valid email address.
</p>
</div>Links within body text must be distinguishable from surrounding text by more than color alone. Use underline (the browser default) or another non-color cue.
/* Good: underline preserved */
a {
color: #0066cc;
text-decoration: underline;
}WCAG 2.2 2.4.13 Focus Appearance (Level AA) requires visible keyboard focus indicators that:
:root {
--focus-ring-color: #0066cc;
--focus-ring-width: 3px;
--focus-ring-offset: 2px;
}
:focus-visible {
outline: var(--focus-ring-width) solid var(--focus-ring-color);
outline-offset: var(--focus-ring-offset);
/* White halo ensures visibility on dark backgrounds */
box-shadow: 0 0 0 calc(var(--focus-ring-width) + var(--focus-ring-offset))
#ffffff;
}
@media (prefers-color-scheme: dark) {
:root {
--focus-ring-color: #99ccff;
}
}/* Works on both light and dark surfaces */
:focus-visible {
outline: 3px solid #000000;
outline-offset: 1px;
box-shadow: 0 0 0 5px #ffffff;
}/* NEVER do this — completely removes focus visibility */
:focus { outline: none; }
/* NEVER do this without providing an alternative focus style */
*:focus { outline: 0 !important; }Windows High Contrast Mode and forced-colors replace author colors with system colors. Interfaces break when CSS background-color, box-shadow, or color properties are the sole means of conveying meaning.
outline for focus rings — it survives forced-colors/* Good: outline is forced-colors-safe */
:focus-visible {
outline: 3px solid Highlight;
outline-offset: 2px;
}
/* Risk: box-shadow may not render in forced-colors mode */
:focus-visible {
box-shadow: 0 0 0 3px #0066cc; /* may be suppressed */
}@media (forced-colors: active) {
.button {
background-color: ButtonFace;
color: ButtonText;
border: 2px solid ButtonBorder;
}
/* Restore SVG icon visibility */
.icon {
forced-color-adjust: auto;
}
}about:config → ui.forcedColors: 1Centralizing all design-system colors as CSS custom properties makes contrast validation and theming manageable at scale.
/* Token layer — raw values */
:root {
--color-neutral-600: #595959; /* 7.0:1 on #fff */
--color-neutral-900: #1a1a1a; /* 16.75:1 on #fff */
--color-brand-500: #0066cc; /* 4.52:1 on #fff — OK for normal text ✓ */
--color-brand-700: #004c99; /* 7.59:1 on #fff — OK for all text ✓ */
/* Semantic layer */
--color-text-primary: var(--color-neutral-900);
--color-text-secondary: var(--color-neutral-600);
--color-text-link: var(--color-brand-500);
--color-surface: #ffffff;
--color-border: #e8e8e8; /* 3:1 for non-text ✓ */
}
@media (prefers-color-scheme: dark) {
:root {
--color-text-primary: #e8e8e8;
--color-text-secondary: #a0a0a0; /* 7.11:1 on #1a1a1a ✓ */
--color-text-link: #66aaff; /* 5.74:1 on #1a1a1a ✓ */
--color-surface: #1a1a1a;
--color-border: #444444; /* 3.1:1 vs #1a1a1a ✓ */
}
}/* Good: references semantic token — works in all themes */
.card {
background-color: var(--color-surface);
color: var(--color-text-primary);
border: 1px solid var(--color-border);
}
/* Bad: hard-coded value that may fail in dark mode */
.card {
background-color: #ffffff;
color: #333;
}The Advanced Perceptual Contrast Algorithm (APCA) is a candidate replacement for the WCAG 2.x contrast ratio formula expected in WCAG 3.0. It models contrast perception more accurately for thin strokes, small font sizes, and saturated colors.
APCA is not yet required. Teams adopting it today must continue to meet WCAG 2.2 AA requirements in parallel.
| Content type | Minimum Lc | Recommended Lc |
|---|---|---|
| Normal body text (16px / 400 weight) | 60 | 75 |
| Large heading text (24px+ / 700 weight) | 45 | 60 |
| UI component labels | 45 | 60 |
| Placeholder / muted text | 30 | 45 |
| Tool | Use case |
|---|---|
| WebAIM Contrast Checker | Quick manual text contrast checks |
| Colour Contrast Analyser (TPGi) | Desktop app for sampling on-screen colors |
| axe DevTools | Browser extension with contrast violation detection |
| apcacontrast.com | APCA-based contrast evaluation |
| Stark (Figma/Sketch plugin) | Design-time contrast checking |
const axe = require("axe-core");
axe.run(document, {
runOnly: {
type: "rule",
values: ["color-contrast", "color-contrast-enhanced"]
}
}, (err, results) => {
if (err) throw err;
console.log("Contrast violations:", results.violations);
});outline, meet 3:1 contrast, and are visible in all modescolor-contrast rule passes in CIStandards horizon: WCAG 3.0's proposed APCA (Advanced Perceptual Contrast Algorithm) will replace the current luminance-ratio model with a perceptual contrast model that treats light-on-dark and dark-on-light differently. Do not apply APCA to production work until WCAG 3.0 is a published standard. Monitor: <https://www.w3.org/TR/wcag-3.0/> and <https://git.apcacontrast.com/>
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.