WCAG Requirements
WCAG Requirements
Color contrast ratios for readability.
Contrast Ratios
| Text Type | AA Ratio | AAA Ratio |
|---|---|---|
| Normal text (< 18pt) | 4.5:1 | 7:1 |
| Large text (≥ 18pt or 14pt bold) | 3:1 | 4.5:1 |
| UI components | 3:1 | 3:1 |
Calculating Contrast
// Contrast ratio formula
function getContrastRatio(rgb1, rgb2) {
const l1 = getRelativeLuminance(rgb1);
const l2 = getRelativeLuminance(rgb2);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
function getRelativeLuminance([r, g, b]) {
const [rs, gs, bs] = [r, g, b].map(c => {
c = c / 255;
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
});
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
}
Color Combinations
/* ✅ Good contrast (7:1) */
.text-high-contrast {
color: #000000;
background: #FFFFFF;
}
/* ✅ Good contrast (4.5:1) */
.text-normal {
color: #595959;
background: #FFFFFF;
}
/* ❌ Poor contrast (2.1:1) */
.text-poor {
color: #999999;
background: #FFFFFF;
}
Contrast Tools
Contrast Tools
Browser Extensions
- axe DevTools: Free, comprehensive
- WAVE: Visual contrast checker
- Colour Contrast Analyser: Desktop app
Online Tools
- WebAIM Contrast Checker: webaim.org/resources/contrastchecker
- Coolors Contrast Checker: coolors.co
- TPGi Contrast Checker: tpgi.com
Code Integration
// Check contrast in tests
import { getContrastRatio } from './accessibility-utils';
describe('Color Contrast', () => {
it('text should have sufficient contrast', () => {
const ratio = getContrastRatio([0, 0, 0], [255, 255, 255]);
expect(ratio).toBeGreaterThanOrEqual(4.5);
});
});
CSS Custom Properties
:root {
/* High contrast theme */
--text-primary: #1a1a1a;
--text-secondary: #595959;
--background: #ffffff;
--border: #767676;
--focus-ring: #005fcc;
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root {
--text-primary: #ffffff;
--text-secondary: #cccccc;
--background: #1a1a1a;
--border: #999999;
--focus-ring: #4da6ff;
}
}
Non-Color Indicators
Non-Color Indicators
Don't rely on color alone to convey information.
Status Indicators
// ❌ Bad: Color only
<span style={{ color: 'red' }}>Error</span>
<span style={{ color: 'green' }}>Success</span>
// ✅ Good: Color + icon/text
<span style={{ color: 'red' }}>
<Icon name="error" /> Error
</span>
<span style={{ color: 'green' }}>
<Icon name="check" /> Success
</span>
// ✅ Good: Icon with sr-only text
<span className="status-error">
<Icon name="error" aria-hidden="true" />
<span className="sr-only">Error:</span> {errorMessage}
</span>
Form Validation
function FormField({ label, error, value }) {
return (
<div>
<label>{label}</label>
<input
value={value}
aria-invalid={!!error}
aria-describedby={error ? `${label}-error` : undefined}
style={{ borderColor: error ? 'red' : 'gray' }}
/>
{error && (
<span id={`${label}-error`} role="alert">
<Icon name="error" /> {error}
</span>
)}
</div>
);
}
Links and Buttons
// ❌ Bad: Color only distinguishes links
<a href="/" style={{ color: 'blue' }}>Link</a>
<span style={{ color: 'gray' }}>Not a link</span>
// ✅ Good: Underline for links
<a href="/" style={{ textDecoration: 'underline' }}>Link</a>
<span>Not a link</span>
// ✅ Good: Explicit button
<button style={{ color: 'red', textDecoration: 'underline' }}>
Delete
</button>
Charts and Graphs
// Use patterns + colors for charts
function BarChart({ data }) {
return (
<div>
{data.map((item, i) => (
<div key={i} className="bar-container">
<div
className={`bar pattern-${i % 3}`}
style={{ backgroundColor: item.color }}
/>
<span>{item.label}: {item.value}</span>
</div>
))}
</div>
);
}
// CSS patterns
.bar.pattern-0 { background-image: repeating-linear-gradient(45deg, transparent, transparent 5px, rgba(255,255,255,0.3) 5px, rgba(255,255,255,0.3) 10px); }
.bar.pattern-1 { background-image: repeating-linear-gradient(-45deg, transparent, transparent 5px, rgba(255,255,255,0.3) 5px, rgba(255,255,255,0.3) 10px); }
.bar.pattern-2 { background-image: repeating-linear-gradient(0deg, transparent, transparent 5px, rgba(255,255,255,0.3) 5px, rgba(255,255,255,0.3) 10px); }
Practice Problems
Create a reusable React component implementing Color Contrast. Include proper state management and accessibility.
Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where neededWrite unit and integration tests for Color Contrast using React Testing Library.
Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility testsOptimize Color Contrast for performance. Consider memoization, code splitting, and bundle size.
Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysisQuiz
1. What is the minimum contrast ratio for normal text?
2. Why not use color alone to convey information?
3. What is the primary purpose of Color Contrast?
4. What is a common mistake when implementing Color Contrast?
Flashcards
Question
What is the minimum contrast ratio for normal text?
Click to reveal answer
Answer
4.5:1 for WCAG AA compliance.
Question
What is non-color indication?
Click to reveal answer
Answer
Using icons, text, or patterns in addition to color to convey information.
Question
Why add underlines to links?
Click to reveal answer
Answer
To distinguish links from regular text for color blind users.
Question
What is WCAG AA?
Click to reveal answer
Answer
The standard level of accessibility compliance requiring 4.5:1 contrast for text.
Question
What is Color Contrast?
Click to reveal answer
Answer
Color Contrast is a key concept in frontend development.
Revision Notes
Key Takeaways
- 1.Normal text needs 4.5:1 contrast ratio
- 2.Large text needs 3:1 contrast ratio
- 3.Never rely on color alone to convey information
- 4.Use icons, text, and patterns with color
- 5.Test with contrast checking tools
Interview Tips
- •Explain WCAG contrast requirements
- •Discuss how to indicate status without color
- •Know common contrast checking tools
Cheat Sheet
Color Contrast Cheat Sheet
WCAG Ratios
- Normal text: 4.5:1 (AA), 7:1 (AAA)
- Large text: 3:1 (AA), 4.5:1 (AAA)
- UI components: 3:1
Tools
- axe DevTools
- WebAIM Contrast Checker
- Colour Contrast Analyser
Non-Color Indicators
- Icons + color
- Text + color
- Patterns + color
- Underlines for links