👁️ 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 TypeNormal TextLarge TextGraphics/UI
Level AA4.5:13:13:1
Level AAA7:14.5:1N/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

  1. Protanopia (Red-blind) - 1% of males
  2. Deuteranopia (Green-blind) - 1% of males
  3. Protanomaly (Red-weak) - 1% of males
  4. Deuteranomaly (Green-weak) - 5% of males
  5. Tritanopia (Blue-blind) - 0.001% of population
  6. 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

Guidelines and Standards

Color Tools

🎯 Key Takeaways

  1. Never rely on color alone - Always provide additional indicators
  2. Test at different zoom levels - Support 200% zoom minimum
  3. Support system preferences - Respect high contrast and reduced motion
  4. Ensure sufficient contrast - WCAG AA is the minimum standard
  5. Design for extremes - If it works in high contrast, it works everywhere

🧭 Quick Navigation

← Voice Control | AI-Generated Code Accessibility → | Accessible Output Formatting →