👁️ Visual Accessibility
Ensuring Claude Code and AI-generated interfaces are visually accessible through proper contrast, color choices, and adaptable display options.
🎯 Overview
Visual accessibility encompasses adaptations for users with low vision, color blindness, light sensitivity, and other visual conditions. This guide covers implementing high contrast modes, ensuring WCAG-compliant color contrast, and creating interfaces that adapt to user visual needs.
🎨 Color Contrast Requirements
WCAG Standards
| Element Type | Normal Text | Large Text | Graphics/UI |
|---|---|---|---|
| Level AA | 4.5:1 | 3:1 | 3:1 |
| Level AAA | 7:1 | 4.5:1 | N/A |
Large text = 18pt (24px) or 14pt (18.5px) bold
Testing Color Contrast
// Calculate contrast ratio between two colors
function getContrastRatio(color1, color2) {
const lum1 = getRelativeLuminance(color1);
const lum2 = getRelativeLuminance(color2);
const lighter = Math.max(lum1, lum2);
const darker = Math.min(lum1, lum2);
return (lighter + 0.05) / (darker + 0.05);
}
function getRelativeLuminance(rgb) {
const [r, g, b] = rgb.map(val => {
const normalized = val / 255;
return normalized <= 0.03928
? normalized / 12.92
: Math.pow((normalized + 0.055) / 1.055, 2.4);
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
// Usage
const ratio = getContrastRatio([255, 255, 255], [0, 0, 0]); // 21:1
const meetsAA = ratio >= 4.5; // true🌓 High Contrast Mode Support
Windows High Contrast Detection
// Detect Windows High Contrast Mode
function isHighContrastMode() {
if (typeof window === 'undefined') return false;
const testElement = document.createElement('div');
testElement.style.borderWidth = '1px';
testElement.style.borderStyle = 'solid';
testElement.style.borderTopColor = 'rgb(255, 0, 0)';
testElement.style.borderBottomColor = 'rgb(0, 255, 0)';
testElement.style.position = 'absolute';
testElement.style.left = '-9999px';
document.body.appendChild(testElement);
const computedStyle = window.getComputedStyle(testElement);
const isHighContrast = computedStyle.borderTopColor === computedStyle.borderBottomColor;
document.body.removeChild(testElement);
return isHighContrast;
}
// CSS Media Query
@media (prefers-contrast: high) {
/* High contrast styles */
.button {
border: 2px solid;
outline: 2px solid transparent;
}
.button:focus {
outline-color: currentColor;
outline-offset: 2px;
}
}Implementing High Contrast Themes
/* Base theme variables */
:root {
--text-primary: #212121;
--text-secondary: #666666;
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
--border-color: #dddddd;
--focus-color: #0066cc;
}
/* High contrast theme */
@media (prefers-contrast: high) {
:root {
--text-primary: #000000;
--text-secondary: #000000;
--bg-primary: #ffffff;
--bg-secondary: #ffffff;
--border-color: #000000;
--focus-color: #000000;
}
/* Increase border widths */
* {
border-width: 2px !important;
}
/* Remove background images */
*[style*="background-image"] {
background-image: none !important;
}
}
/* Dark high contrast */
@media (prefers-contrast: high) and (prefers-color-scheme: dark) {
:root {
--text-primary: #ffffff;
--text-secondary: #ffffff;
--bg-primary: #000000;
--bg-secondary: #000000;
--border-color: #ffffff;
--focus-color: #ffffff;
}
}🎨 Color Blindness Support
Common Types of Color Blindness
- Protanopia (Red-blind) - 1% of males
- Deuteranopia (Green-blind) - 1% of males
- Protanomaly (Red-weak) - 1% of males
- Deuteranomaly (Green-weak) - 5% of males
- Tritanopia (Blue-blind) - 0.001% of population
- Achromatopsia (Complete color blindness) - Very rare
Color-Safe Palettes
// Color-blind safe palette
const accessibleColors = {
// Use these instead of pure red/green
success: '#0077BB', // Blue instead of green
error: '#CC3311', // Orange-red with high luminance
warning: '#EE7733', // Orange
info: '#009988', // Teal
// High contrast options
primary: '#0033CC',
secondary: '#663399',
// Semantic colors with patterns
statusColors: {
active: { color: '#0077BB', pattern: 'solid' },
inactive: { color: '#BBBBBB', pattern: 'dashed' },
error: { color: '#CC3311', pattern: 'wavy' },
success: { color: '#009988', pattern: 'dotted' }
}
};Using Patterns and Shapes
/* Don't rely on color alone */
.status-indicator {
width: 20px;
height: 20px;
border-radius: 50%;
}
/* Add patterns for color blindness */
.status-success {
background-color: #0077BB;
background-image: url("data:image/svg+xml,%3Csvg width='4' height='4' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='2' cy='2' r='1' fill='white'/%3E%3C/svg%3E");
}
.status-error {
background-color: #CC3311;
background-image: url("data:image/svg+xml,%3Csvg width='4' height='4' xmlns='http://www.w3.org/2000/svg'%3E%3Cline x1='0' y1='0' x2='4' y2='4' stroke='white'/%3E%3C/svg%3E");
}
/* Use shapes as additional indicators */
.status-success::before { content: '✓'; }
.status-error::before { content: '✗'; }
.status-warning::before { content: '!'; }📱 Responsive Text and Zoom
Supporting Browser Zoom
/* Use relative units for better zoom support */
html {
font-size: 100%; /* 16px default */
}
body {
font-size: 1rem;
line-height: 1.5;
}
/* Responsive typography */
h1 { font-size: clamp(1.75rem, 4vw, 2.5rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2rem); }
h3 { font-size: clamp(1.25rem, 2.5vw, 1.75rem); }
/* Ensure containers don't break on zoom */
.container {
max-width: 100%;
overflow-wrap: break-word;
}
/* Prevent horizontal scroll on zoom */
* {
max-width: 100%;
box-sizing: border-box;
}Text Spacing Adjustments
/* WCAG 2.1 Success Criterion 1.4.12 */
/* Support user stylesheet overrides */
* {
/* Allow 200% line height */
line-height: inherit !important;
/* Allow 200% letter spacing */
letter-spacing: inherit !important;
/* Allow 250% word spacing */
word-spacing: inherit !important;
/* Allow 200% paragraph spacing */
margin-bottom: inherit !important;
}🖥️ Claude Code Terminal Visual Accessibility
High Contrast Terminal Themes
// Claude Code terminal theme system
const terminalThemes = {
standard: {
background: '#1e1e1e',
foreground: '#cccccc',
cursor: '#ffffff',
selection: '#3a3d41'
},
highContrast: {
background: '#000000',
foreground: '#ffffff',
cursor: '#00ff00',
selection: '#ffffff33',
// Increased font weight
fontWeight: 'bold'
},
highContrastLight: {
background: '#ffffff',
foreground: '#000000',
cursor: '#000000',
selection: '#00000033',
fontWeight: 'bold'
},
// Color-blind friendly theme
deuteranopia: {
// Avoid red-green combinations
error: '#CC3311', // Orange-red
success: '#0077BB', // Blue
warning: '#EE7733', // Orange
info: '#009988' // Teal
}
};Terminal Font Adjustments
# Recommended accessible terminal settings
# Font size (minimum 14pt)
terminal.integrated.fontSize: 14
# Font family (monospace with good character distinction)
terminal.integrated.fontFamily: 'Cascadia Code, Consolas, monospace'
# Line height (1.5x for readability)
terminal.integrated.lineHeight: 1.5
# Cursor style (block for visibility)
terminal.integrated.cursorStyle: 'block'
terminal.integrated.cursorBlinking: 'solid'🎯 AI-Generated Code Visual Accessibility
Ensuring Accessible Output
// Claude Code should generate visually accessible code
class AccessibleCodeGenerator {
generateButton(text: string, action: string): string {
return `
<button
class="btn btn-primary"
onclick="${action}"
style="
/* WCAG AA compliant contrast */
background-color: #0066cc;
color: #ffffff;
border: 2px solid #0052a3;
padding: 0.5rem 1rem;
font-size: 1rem;
cursor: pointer;
"
>
${text}
</button>
<style>
/* High contrast mode support */
@media (prefers-contrast: high) {
.btn {
border-width: 3px !important;
font-weight: bold !important;
}
}
/* Focus styles */
.btn:focus {
outline: 3px solid #ff9900;
outline-offset: 2px;
}
</style>
`.trim();
}
generateColorScheme(): ColorScheme {
return {
// Always include non-color indicators
states: {
success: { color: '#0077BB', icon: '✓', label: 'Success' },
error: { color: '#CC3311', icon: '✗', label: 'Error' },
warning: { color: '#EE7733', icon: '⚠', label: 'Warning' },
info: { color: '#009988', icon: 'ℹ', label: 'Info' }
}
};
}
}🔍 Visual Accessibility Testing
Manual Testing Checklist
-
Color Contrast
- Text meets WCAG AA standards (4.5:1)
- UI elements meet 3:1 contrast ratio
- Focus indicators are clearly visible
-
High Contrast Mode
- Enable Windows High Contrast
- All content remains visible
- No information lost
-
Browser Zoom
- Zoom to 200% - no horizontal scroll
- Zoom to 400% - content still usable
- Text remains readable
-
Color Blindness
- Use browser extensions to simulate
- Information not conveyed by color alone
- Status indicators use shapes/patterns
Automated Testing Tools
// Puppeteer accessibility testing
const { AxePuppeteer } = require('@axe-core/puppeteer');
const puppeteer = require('puppeteer');
async function testVisualAccessibility(url) {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(url);
// Test standard view
const results = await new AxePuppeteer(page)
.withTags(['wcag2aa', 'wcag21aa'])
.analyze();
// Test with forced colors
await page.emulateMediaFeatures([
{ name: 'prefers-contrast', value: 'high' }
]);
const highContrastResults = await new AxePuppeteer(page).analyze();
// Test zoom levels
await page.setViewport({ width: 1280, height: 720, deviceScaleFactor: 2 });
const zoomResults = await new AxePuppeteer(page).analyze();
await browser.close();
return { results, highContrastResults, zoomResults };
}💡 Best Practices
1. Don’t Rely on Color Alone
<!-- ❌ Bad: Color only -->
<span style="color: red;">Error</span>
<!-- ✅ Good: Multiple indicators -->
<span class="error" aria-label="Error">
<svg class="icon-error" aria-hidden="true">...</svg>
Error
</span>2. Provide User Control
// Allow users to customize visual settings
class VisualPreferences {
constructor() {
this.settings = {
fontSize: this.loadSetting('fontSize', '16'),
contrast: this.loadSetting('contrast', 'normal'),
colorScheme: this.loadSetting('colorScheme', 'default'),
reducedMotion: this.loadSetting('reducedMotion', 'auto')
};
}
applySettings() {
document.documentElement.style.fontSize = `${this.settings.fontSize}px`;
document.documentElement.setAttribute('data-contrast', this.settings.contrast);
document.documentElement.setAttribute('data-theme', this.settings.colorScheme);
}
increaseFontSize() {
this.settings.fontSize = Math.min(32, parseInt(this.settings.fontSize) + 2);
this.saveSetting('fontSize', this.settings.fontSize);
this.applySettings();
}
}3. Test with Real Users
“Nothing about us without us” - Disability rights motto
Always include users with visual impairments in your testing process.
📚 Resources
Testing Tools
- WAVE - Web accessibility evaluation
- Stark - Design accessibility toolkit
- Colorblinding - Chrome extension
- Windows High Contrast Mode
Guidelines and Standards
Color Tools
- WebAIM Contrast Checker
- Accessible Colors
- Colorbrewer - Color-blind safe palettes
- Sim Daltonism - Color blindness simulator
🎯 Key Takeaways
- Never rely on color alone - Always provide additional indicators
- Test at different zoom levels - Support 200% zoom minimum
- Support system preferences - Respect high contrast and reduced motion
- Ensure sufficient contrast - WCAG AA is the minimum standard
- Design for extremes - If it works in high contrast, it works everywhere
🧭 Quick Navigation
← Voice Control | AI-Generated Code Accessibility → | Accessible Output Formatting →