npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bernierllc/validators-a11y-contrast

v0.3.0

Published

Accessibility color contrast validation for the BernierLLC validators ecosystem - validates WCAG AA and AAA contrast requirements

Readme

@bernierllc/validators-a11y-contrast

Accessibility color contrast validation for the BernierLLC validators ecosystem - validates WCAG AA and AAA contrast requirements.

Installation

npm install @bernierllc/validators-a11y-contrast

Overview

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 Standards Supported

  • 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)

Text Size Definitions

  • Normal Text: Below 18pt (24px) or below 14pt (18.67px) bold
  • Large Text: 18pt (24px)+ or 14pt (18.67px)+ bold

Usage

Basic Validation

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}`);
  console.log(`Suggestion: ${problem.suggestion}`);
});

Quick Contrast Check

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`);
console.log(`Required: ${result.required}:1`);
console.log(`Passes: ${result.passes}`);
// Output:
// Contrast Ratio: 21.00:1
// Required: 4.5:1
// Passes: true

Large Text Validation

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

WCAG AAA Enhanced Validation

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

Non-Text UI Elements

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

API Reference

validateA11yContrast(input, utils?)

Validates color contrast against WCAG standards and returns validation problems.

Parameters:

  • input: ContrastCheckInput - Validation configuration
    • foreground: string - Foreground color (text/UI element)
    • background: string - Background color
    • level?: '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<Problem[]> - Array of validation problems

Color Format Support:

  • Hex: #000, #000000
  • RGB: rgb(0, 0, 0), rgba(0, 0, 0, 1)
  • Named: black, white, red, etc.

checkContrast(input)

Synchronously checks contrast and returns detailed metrics.

Parameters:

  • input: ContrastCheckInput - Same as validateA11yContrast

Returns: ContrastCheckResult

  • passes: boolean - Whether contrast meets requirements
  • contrastRatio: number - Calculated contrast ratio
  • required: number - Required minimum ratio
  • level: 'AA' | 'AAA' - WCAG level checked
  • fontSize?: 'normal' | 'large' - Text size (if text)
  • elementType: 'text' | 'non-text' - Element type

Validation Rules

Rule: a11y-contrast/insufficient-contrast-aa-normal

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'

Rule: a11y-contrast/insufficient-contrast-aa-large

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'

Rule: a11y-contrast/insufficient-contrast-aaa-normal

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'

Rule: a11y-contrast/insufficient-contrast-aaa-large

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'

Rule: a11y-contrast/insufficient-contrast-non-text

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'

Real-World Examples

Validating Link Colors

// 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

Button Border Contrast

// 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

Form Input Validation

// 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)"

Dark Mode Validation

// 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

Integration with Other Validators

This primitive validator can be composed with other validators in the ecosystem:

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
);

Dependencies

  • @bernierllc/validators-core - Core validation framework
  • @bernierllc/validators-utils - Shared utilities including color parsing and contrast calculation

Integration Status

Logger Integration

Not applicable - This is a pure validation utility with no side effects or logging requirements. As a primitive validator focused solely on color contrast calculations, it follows the validators architecture principle where logging is handled by higher-level domain validators or the validation runner.

Docs-Suite Compatibility

Ready - Package includes complete markdown documentation that can be integrated into docs-suite. All validation rules are documented with examples and usage patterns.

NeverHub Integration

Not applicable - This is a primitive validator that operates synchronously on input data. Following the validators architecture, primitive validators do not integrate with NeverHub. Service discovery and event publishing are responsibilities of domain validators and validator orchestrators that consume this primitive.

Testing

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Run tests once
npm run test:run

Quality Standards

  • Test Coverage: 90%+ (branches, functions, lines, statements)
  • TypeScript: Strict mode enabled
  • Linting: Zero errors or warnings
  • Real Data: Tests use actual color values

Contributing

This package follows BernierLLC standards:

  • Single responsibility (contrast validation only)
  • Pure functions
  • Comprehensive test coverage
  • Real-world testing data

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

See Also