Accessibility color contrast validation for the BernierLLC validators ecosystem - validates WCAG AA and AAA contrast requirements
npm install @bernierllc/validators-a11y-contrastAccessibility color contrast validation for the BernierLLC validators ecosystem - validates WCAG AA and AAA contrast requirements.
``bash`
npm install @bernierllc/validators-a11y-contrast
This primitive validator checks color contrast ratios against WCAG 2.1 accessibility standards. It validates both text and non-text UI elements to ensure sufficient contrast for users with visual impairments.
- WCAG AA Text: 4.5:1 minimum for normal text, 3:1 for large text
- WCAG AAA Text: 7:1 minimum for normal text, 4.5:1 for large text
- Non-Text Elements: 3:1 minimum (WCAG 2.1 SC 1.4.11)
- Normal Text: Below 18pt (24px) or below 14pt (18.67px) bold
- Large Text: 18pt (24px)+ or 14pt (18.67px)+ bold
`typescript
import { validateA11yContrast } from '@bernierllc/validators-a11y-contrast';
// Check normal text against WCAG AA
const problems = await validateA11yContrast({
foreground: '#777777',
background: '#ffffff',
level: 'AA',
fontSize: 'normal'
});
problems.forEach(problem => {
console.log(${problem.severity}: ${problem.message});Suggestion: ${problem.suggestion}
console.log();`
});
`typescript
import { checkContrast } from '@bernierllc/validators-a11y-contrast';
// Get detailed contrast metrics
const result = checkContrast({
foreground: '#000000',
background: '#ffffff',
level: 'AA',
fontSize: 'normal'
});
console.log(Contrast Ratio: ${result.contrastRatio.toFixed(2)}:1);Required: ${result.required}:1
console.log();Passes: ${result.passes}
console.log();`
// Output:
// Contrast Ratio: 21.00:1
// Required: 4.5:1
// Passes: true
`typescript
import { validateA11yContrast } from '@bernierllc/validators-a11y-contrast';
// Headers and large text have lower requirements
const problems = await validateA11yContrast({
foreground: '#959595',
background: '#ffffff',
level: 'AA',
fontSize: 'large'
});
// Passes with 3.5:1 ratio (minimum 3:1 for large text)
console.log(problems.length); // 0
`
`typescript
import { validateA11yContrast } from '@bernierllc/validators-a11y-contrast';
// Check against enhanced AAA standards
const problems = await validateA11yContrast({
foreground: '#595959',
background: '#ffffff',
level: 'AAA',
fontSize: 'normal'
});
// Passes with 7.1:1 ratio (minimum 7:1 for AAA normal text)
console.log(problems.length); // 0
`
`typescript
import { validateA11yContrast } from '@bernierllc/validators-a11y-contrast';
// Validate button borders, icons, and graphical elements
const problems = await validateA11yContrast({
foreground: '#0066cc',
background: '#ffffff',
elementType: 'non-text'
});
// Passes with 7.9:1 ratio (minimum 3:1 for non-text)
console.log(problems.length); // 0
`
Validates color contrast against WCAG standards and returns validation problems.
Parameters:
- input: ContrastCheckInput - Validation configurationforeground: string
- - Foreground color (text/UI element)background: string
- - Background colorlevel?: 'AA' | 'AAA'
- - WCAG level (default: 'AA')fontSize?: 'normal' | 'large'
- - Text size category (default: 'normal')elementType?: 'text' | 'non-text'
- - Element type (default: 'text')utils?: SharedUtils
- - Optional shared utilities
Returns: Promise - Array of validation problems
Color Format Support:
- Hex: #000, #000000rgb(0, 0, 0)
- RGB: , rgba(0, 0, 0, 1)black
- Named: , white, red, etc.
Synchronously checks contrast and returns detailed metrics.
Parameters:
- input: ContrastCheckInput - Same as validateA11yContrast
Returns: ContrastCheckResultpasses: boolean
- - Whether contrast meets requirementscontrastRatio: number
- - Calculated contrast ratiorequired: number
- - Required minimum ratiolevel: 'AA' | 'AAA'
- - WCAG level checkedfontSize?: 'normal' | 'large'
- - Text size (if text)elementType: 'text' | 'non-text'
- - Element type
Severity: error
Validates normal text meets WCAG AA minimum of 4.5:1 contrast ratio.
Triggers When:
- Text contrast ratio < 4.5:1
- Element type is 'text'
- Font size is 'normal'
- Level is 'AA'
Severity: error
Validates large text meets WCAG AA minimum of 3:1 contrast ratio.
Triggers When:
- Text contrast ratio < 3:1
- Element type is 'text'
- Font size is 'large'
- Level is 'AA'
Severity: warning
Validates normal text meets WCAG AAA enhanced minimum of 7:1.
Triggers When:
- Text contrast ratio < 7:1
- Element type is 'text'
- Font size is 'normal'
- Level is 'AAA'
Severity: warning
Validates large text meets WCAG AAA enhanced minimum of 4.5:1.
Triggers When:
- Text contrast ratio < 4.5:1
- Element type is 'text'
- Font size is 'large'
- Level is 'AAA'
Severity: error
Validates non-text elements meet WCAG 2.1 SC 1.4.11 minimum of 3:1.
Triggers When:
- UI element contrast < 3:1
- Element type is 'non-text'
`typescript
// Standard link blue on white background
const linkProblems = await validateA11yContrast({
foreground: '#0000ee',
background: '#ffffff',
level: 'AA',
fontSize: 'normal'
});
console.log(linkProblems.length); // 0 - Passes with 8.6:1 ratio
`
`typescript
// Validate button border stands out
const borderProblems = await validateA11yContrast({
foreground: '#0066cc', // Button border color
background: '#ffffff', // Page background
elementType: 'non-text'
});
console.log(borderProblems.length); // 0 - Passes with 7.9:1 ratio
`
`typescript
// Check placeholder text color
const placeholderProblems = await validateA11yContrast({
foreground: '#999999', // Light gray placeholder
background: '#ffffff',
level: 'AA',
fontSize: 'normal'
});
console.log(placeholderProblems.length); // 1 - Fails with 2.85:1 ratio
console.log(placeholderProblems[0].message);
// "Insufficient contrast ratio 2.85:1 (minimum 4.5:1 required for WCAG AA)"
`
`typescript
// Validate dark mode text
const darkModeProblems = await validateA11yContrast({
foreground: '#e0e0e0', // Light text
background: '#1a1a1a', // Dark background
level: 'AA',
fontSize: 'normal'
});
console.log(darkModeProblems.length); // 0 - Passes with 11.8:1 ratio
`
This primitive validator can be composed with other validators in the ecosystem:
`typescript
import { createRuleContext } from '@bernierllc/validators-core';
import { createSharedUtils } from '@bernierllc/validators-utils';
import { a11yContrastValidator } from '@bernierllc/validators-a11y-contrast';
// Create shared utilities once
const utils = createSharedUtils();
// Create context for validation
const context = createRuleContext(
'a11y-contrast',
{ foreground: '#777', background: '#fff' },
utils
);
// Run validation
const problems = await a11yContrastValidator.validate(
{ foreground: '#777', background: '#fff', level: 'AA', fontSize: 'normal' },
context
);
`
- @bernierllc/validators-core - Core validation framework@bernierllc/validators-utils
- - Shared utilities including color parsing and contrast calculation
`bashRun tests
npm test
- Test Coverage: 90%+ (branches, functions, lines, statements)
- TypeScript: Strict mode enabled
- Linting: Zero errors or warnings
- Real Data: Tests use actual color values
This package follows BernierLLC standards:
- Single responsibility (contrast validation only)
- Pure functions
- Comprehensive test coverage
- Real-world testing data
Copyright (c) 2025 Bernier LLC. All rights reserved.
- @bernierllc/validators-core - Core validation framework
- @bernierllc/validators-utils - Shared validation utilities
- @bernierllc/validators-html-syntax - HTML syntax validation
- WCAG 2.1 Guidelines - Official WCAG documentation