Accessibility Guide
This guide covers creating accessible color combinations that meet WCAG (Web Content Accessibility Guidelines) standards.
Understanding Color Accessibility
Color accessibility ensures that content is usable by people with various visual impairments, including:
Color blindness (affecting ~8% of men and ~0.5% of women)
Low vision conditions
Age-related vision changes
Different viewing conditions (bright sunlight, low-quality displays)
WCAG Guidelines
The Web Content Accessibility Guidelines define contrast requirements:
- Contrast Ratios
AA Level: 4.5:1 for normal text, 3:1 for large text
AAA Level: 7:1 for normal text, 4.5:1 for large text
- Text Size Classifications
Normal text: Under 18pt regular or 14pt bold
Large text: 18pt+ regular or 14pt+ bold
Quick Accessibility Check
Use the built-in functions to check if color combinations are accessible:
from chromo_map import Color, contrast_ratio, is_accessible
# Check contrast ratio
text_color = Color('#333333')
background = Color('#ffffff')
ratio = contrast_ratio(text_color, background)
print(f"Contrast ratio: {ratio:.2f}") # 12.63
# Check WCAG compliance
aa_compliant = is_accessible(text_color, background, level='AA')
aaa_compliant = is_accessible(text_color, background, level='AAA')
print(f"AA compliant: {aa_compliant}") # True
print(f"AAA compliant: {aaa_compliant}") # True
Making Colors Accessible
When you have a color that doesn’t meet accessibility requirements, use the optimization functions:
Basic Accessibility
from chromo_map import find_accessible_color
# Start with a brand color that might not be accessible
brand_color = '#ff6b6b' # Light red
background = 'white'
# Make it accessible
accessible_color = find_accessible_color(brand_color, background, level='AA')
print(f"Original: {brand_color}")
print(f"Accessible: {accessible_color.hex}")
print(f"Contrast: {accessible_color.contrast_ratio(Color(background)):.2f}")
Maximum Contrast Optimization
For the best possible contrast while maintaining color character:
from chromo_map import find_maximal_contrast_binary_search
# Find maximum contrast version
optimized = find_maximal_contrast_binary_search('#ff6b6b', 'white')
print(f"Optimized color: {optimized.hex}")
print(f"Contrast ratio: {optimized.contrast_ratio(Color('white')):.2f}")
Practical Examples
Website Color Palette
from chromo_map import Color, find_accessible_color
# Brand colors
primary = '#3498db' # Blue
secondary = '#e74c3c' # Red
accent = '#f39c12' # Orange
# Background colors
light_bg = '#ffffff' # White
dark_bg = '#2c3e50' # Dark blue
# Ensure all combinations are accessible
primary_on_light = find_accessible_color(primary, light_bg)
secondary_on_light = find_accessible_color(secondary, light_bg)
accent_on_light = find_accessible_color(accent, light_bg)
# For dark backgrounds, often we need lighter text
primary_on_dark = find_accessible_color(primary, dark_bg)
print("Accessible color palette:")
print(f"Primary on light: {primary_on_light.hex}")
print(f"Secondary on light: {secondary_on_light.hex}")
print(f"Accent on light: {accent_on_light.hex}")
print(f"Primary on dark: {primary_on_dark.hex}")
Form Validation Colors
from chromo_map import find_accessible_color
# Common form validation colors
success_base = '#28a745' # Green
warning_base = '#ffc107' # Yellow
error_base = '#dc3545' # Red
info_base = '#17a2b8' # Cyan
background = '#ffffff'
# Make all accessible for text on white background
success_text = find_accessible_color(success_base, background)
warning_text = find_accessible_color(warning_base, background)
error_text = find_accessible_color(error_base, background)
info_text = find_accessible_color(info_base, background)
validation_colors = {
'success': success_text.hex,
'warning': warning_text.hex,
'error': error_text.hex,
'info': info_text.hex
}
print("Accessible validation colors:", validation_colors)
Color Blindness Considerations
Beyond contrast, consider color blindness when choosing colors:
- Problematic Combinations
Red/green (most common color blindness)
Blue/purple
Green/brown
Safe Strategies
from chromo_map import Color
# Use colors that are distinguishable across color blindness types
safe_colors = [
Color('#d73027'), # Red (safe red)
Color('#1a9850'), # Green (safe green)
Color('#313695'), # Blue
Color('#f46d43'), # Orange
Color('#a50026'), # Dark red
Color('#74add1') # Light blue
]
# Test: These colors have good separation in HSV space
for i, color in enumerate(safe_colors):
print(f"Color {i+1}: {color.hex} (H:{color.hue:.0f}°)")
- Use Additional Visual Cues
Don’t rely on color alone. Combine with: - Icons or symbols - Patterns or textures - Typography (bold, italic) - Positioning
Testing Your Colors
Automated Testing
from chromo_map import Color, is_accessible
def test_color_accessibility(colors, backgrounds):
"""Test all color/background combinations."""
results = []
for color in colors:
for bg in backgrounds:
color_obj = Color(color)
bg_obj = Color(bg)
ratio = color_obj.contrast_ratio(bg_obj)
aa = is_accessible(color, bg, level='AA')
aaa = is_accessible(color, bg, level='AAA')
results.append({
'color': color,
'background': bg,
'ratio': ratio,
'aa': aa,
'aaa': aaa
})
return results
# Test your palette
text_colors = ['#333333', '#666666', '#999999']
backgrounds = ['#ffffff', '#f8f9fa', '#e9ecef']
test_results = test_color_accessibility(text_colors, backgrounds)
for result in test_results:
if result['aa']:
print(f"✅ {result['color']} on {result['background']}: {result['ratio']:.2f}")
else:
print(f"❌ {result['color']} on {result['background']}: {result['ratio']:.2f}")
- Manual Testing Tools
Browser developer tools (accessibility audits)
Color blindness simulators
Real testing with users who have visual impairments
Advanced Accessibility Features
Progressive Enhancement
from chromo_map import Color, find_accessible_color
def create_accessible_theme(base_color, backgrounds):
"""Create progressively accessible color variations."""
base = Color(base_color)
theme = {}
for bg_name, bg_color in backgrounds.items():
# Different accessibility levels
theme[f'{bg_name}_aa'] = find_accessible_color(
base_color, bg_color, level='AA'
).hex
theme[f'{bg_name}_aaa'] = find_accessible_color(
base_color, bg_color, level='AAA'
).hex
return theme
# Create adaptive theme
backgrounds = {
'light': '#ffffff',
'medium': '#f5f5f5',
'dark': '#333333'
}
brand_theme = create_accessible_theme('#3498db', backgrounds)
print(brand_theme)
Dynamic Contrast Adjustment
from chromo_map import Color, find_maximal_contrast_optimization
def get_optimal_text_color(background_color):
"""Get the best text color for any background."""
bg = Color(background_color)
# Test both black and white text
black_contrast = Color('#000000').contrast_ratio(bg)
white_contrast = Color('#ffffff').contrast_ratio(bg)
if black_contrast > white_contrast:
# Optimize black text
return find_maximal_contrast_optimization('#000000', background_color)
else:
# Optimize white text
return find_maximal_contrast_optimization('#ffffff', background_color)
# Example usage
backgrounds = ['#3498db', '#e74c3c', '#f39c12', '#2ecc71']
for bg in backgrounds:
optimal_text = get_optimal_text_color(bg)
print(f"Background: {bg} → Text: {optimal_text.hex}")
Best Practices Summary
Always test contrast ratios before finalizing color choices
Aim for AAA compliance when possible, especially for body text
Use multiple visual cues beyond color alone
Test with actual users who have visual impairments
Consider viewing conditions (mobile devices, bright sunlight)
Maintain brand identity while ensuring accessibility
Document your accessible color palette for consistent use
Tools and Resources
- chromo-map Functions
contrast_ratio()
- Calculate WCAG contrast ratiosis_accessible()
- Check WCAG compliancefind_accessible_color()
- Make colors accessiblefind_maximal_contrast_*()
- Optimize for maximum contrast
- External Tools
WebAIM Contrast Checker
Colour Contrast Analyser (CCA)
axe DevTools browser extension
- Testing
Lighthouse accessibility audits
WAVE (Web Accessibility Evaluation Tool)
Color blindness simulators
Remember: Accessibility benefits everyone, not just users with disabilities. High-contrast, well-chosen colors improve readability and user experience for all users.