Accessible Color Hierarchy for Headings
Create an accessible visual hierarchy using color contrast for headings, subheadings, and body text. Learn how to use contrast levels to establish typographic importance.
Detailed Explanation
Building a Color Hierarchy
Typography hierarchy relies on size, weight, and color to indicate importance. Using lighter colors for less important text is a common pattern, but each level must still meet WCAG contrast requirements.
Hierarchy Pattern on White Background
/* Heading levels with decreasing emphasis */
h1 {
color: #0f172a; /* slate-900: 17.58:1 vs white - AAA */
font-size: 36px;
font-weight: 800;
}
h2 {
color: #1e293b; /* slate-800: 14.14:1 vs white - AAA */
font-size: 30px;
font-weight: 700;
}
h3 {
color: #334155; /* slate-700: 10.26:1 vs white - AAA */
font-size: 24px; /* Large text: needs 3:1 */
font-weight: 600;
}
body {
color: #475569; /* slate-600: 7.09:1 vs white - AAA */
font-size: 16px;
font-weight: 400;
}
.text-muted {
color: #64748b; /* slate-500: 4.88:1 vs white - AA */
font-size: 14px;
}
.text-caption {
color: #94a3b8; /* slate-400: 3.15:1 vs white */
font-size: 12px;
/* WARNING: Fails AA for normal text */
}
The Muted Text Trap
Designers often want a very light "muted" text color for captions, timestamps, or metadata. However, text lighter than approximately #767676 (contrast 4.54:1) fails AA for normal text on white. Solutions include:
- Accept the darkest acceptable gray:
#6b7280(gray-500) at 5.03:1 - Increase font size: If the text is 18px bold or 24px regular, you only need 3:1
- Use weight as a differentiator: Keep the same color but reduce font weight
Hierarchy on Dark Background
/* Dark mode hierarchy on #0f172a */
h1 { color: #f8fafc; } /* slate-50: 18.31:1 - AAA */
h2 { color: #f1f5f9; } /* slate-100: 16.56:1 - AAA */
h3 { color: #e2e8f0; } /* slate-200: 13.90:1 - AAA */
body { color: #cbd5e1; } /* slate-300: 10.35:1 - AAA */
.text-muted { color: #94a3b8; } /* slate-400: 6.48:1 - AA */
Maintaining Consistency
Use CSS custom properties or design tokens to ensure your hierarchy is consistent across pages. Map each level to a semantic name like --text-heading, --text-body, --text-muted rather than using raw color values.
Use Case
Apply this pattern when establishing the typographic hierarchy for a design system. Define accessible color tokens for each text level and document the minimum contrast ratio each level provides.