Skip to main content
colorscope

Accessibility

Check WCAG contrast ratios, simulate color vision deficiencies, and audit palettes for color blindness safety.

Material

Text color

Color vision simulation

Emerald Tile

ET-4021

Spec
FinishGlazed ceramic
Size200 × 200 mm
Color#1B7340
Contrast ratio5.88:1
AAAAAAA LargeAAA Large
Best foreground#ffffff
5.88:1AA
import { contrastRatio, meetsWCAG, simulateColorBlindnessHex } from "colorscope/accessibility";

Contrast

contrastRatio

Calculate WCAG contrast ratio between two colors.

function contrastRatio(color1: ColorInput, color2: ColorInput): number
ParamTypeDescription
color1ColorInputFirst color
color2ColorInputSecond color

Returns: Value from 1 (identical) to 21 (black vs white).

contrastRatio("#000000", "#ffffff"); // 21
contrastRatio("#ff6600", "#ffffff"); // ~3.0

meetsWCAG

Check WCAG compliance for a color pair.

function meetsWCAG(color1: ColorInput, color2: ColorInput): WCAGResult

Returns: Pass/fail for AA, AAA, and large text variants, plus the actual ratio.

const result = meetsWCAG("#1a1a1a", "#ffffff");
// { aa: true, aaa: true, aaLarge: true, aaaLarge: true, ratio: 17.58 }

relativeLuminance

Calculate WCAG 2.x relative luminance from RGB.

function relativeLuminance(r: number, g: number, b: number): number

Returns: Value from 0 (black) to 1 (white).

suggestAccessibleForeground

Suggest the best foreground color for a given background.

function suggestAccessibleForeground(
  background: ColorInput,
  candidates?: readonly ColorInput[]
): { color: RGB; hex: string; ratio: number }
ParamTypeDefaultDescription
backgroundColorInputBackground color
candidatesreadonly ColorInput[][black, white]Candidate foreground colors

Tests each candidate and returns the one with the highest contrast ratio.

suggestAccessibleForeground("#1a1a1a");
// { color: { r: 255, g: 255, b: 255 }, hex: "#ffffff", ratio: 17.58 }

suggestAccessibleForeground("#ffcc00", ["#000000", "#ffffff", "#333333"]);
// { color: { r: 0, g: 0, b: 0 }, hex: "#000000", ratio: 15.95 }

Color Vision Deficiency

simulateColorBlindness

Simulate how a color appears to someone with a color vision deficiency.

function simulateColorBlindness(
  color: string | RGB | QuantizedColor,
  type: ColorBlindnessType
): RGB
ParamTypeDescription
colorstring | RGB | QuantizedColorInput color
typeColorBlindnessTypeType of CVD to simulate

Uses Viénot, Brettel & Mollon (1999) simulation matrices in linear RGB space. Achromatopsia uses luminance conversion.

simulateColorBlindnessHex

Simulate color blindness and return as hex string.

function simulateColorBlindnessHex(
  color: string | RGB | QuantizedColor,
  type: ColorBlindnessType
): string
simulateColorBlindnessHex("#ff0000", "deuteranopia"); // "#9a8700"

checkColorBlindSafety

Check if a palette is safe for people with color vision deficiencies.

function checkColorBlindSafety(
  palette: readonly QuantizedColor[],
  types?: readonly ColorBlindnessType[]
): ColorBlindSafetyReport[]
ParamTypeDefaultDescription
palettereadonly QuantizedColor[]Colors to check
typesreadonly ColorBlindnessType[]All four typesTypes to test

Tests each pair of colors: if two colors are distinguishable in normal vision but become very similar when simulated, they're flagged as confusable.

Returns: Safety report for each CVD type.

const reports = checkColorBlindSafety(colors);
for (const report of reports) {
  console.log(`${report.type}: ${report.safe ? "safe" : "has confusable pairs"}`);
}

Types

WCAGResult

interface WCAGResult {
  aa: boolean;      // Passes AA for normal text (≥4.5:1)
  aaa: boolean;     // Passes AAA for normal text (≥7:1)
  aaLarge: boolean;  // Passes AA for large text (≥3:1)
  aaaLarge: boolean; // Passes AAA for large text (≥4.5:1)
  ratio: number;    // The actual contrast ratio
}

ColorInput

type ColorInput =
  | string                                                    // hex string
  | RGB                                                       // { r, g, b }
  | { hue: number; saturation: number; lightness: number }    // HSL-like

ColorBlindnessType

type ColorBlindnessType = "protanopia" | "deuteranopia" | "tritanopia" | "achromatopsia"

ColorBlindSafetyReport

interface ColorBlindSafetyReport {
  type: ColorBlindnessType;
  confusablePairs: Array<{
    indexA: number;
    indexB: number;
    originalDistance: number;
    simulatedDistance: number;
  }>;
  safe: boolean;  // true if no confusable pairs
}