@siluat/color-contrast
v1.0.0
Published
WCAG color contrast ratio computation library
Maintainers
Readme
@siluat/color-contrast
WCAG color contrast ratio computation library. Zero runtime dependencies, browser compatible.
Installation
npm install @siluat/color-contrast
# or
pnpm add @siluat/color-contrast
# or
bun add @siluat/color-contrastJSR
deno add jsr:@siluat/color-contrast
# or
npx jsr add @siluat/color-contrastContrast Ratio
import { contrastRatio } from '@siluat/color-contrast';
contrastRatio('#000000', '#ffffff'); // 21
contrastRatio('#00000080', '#ffffff'); // alpha compositing supported
contrastRatio('rgb(0, 0, 0)', '#fff'); // RGB functional notation
contrastRatio('navy', 'white'); // CSS named colors
contrastRatio('oklch(60% 0.15 50)', 'white'); // wide-gamut colorsReturns the ratio as a number.
WCAG Compliance Check
import { checkContrast } from '@siluat/color-contrast';
checkContrast('#333', '#fff');
// { ratio: 12.63, normalText: 'AAA', largeText: 'AAA' }
checkContrast('#777', '#fff');
// { ratio: 4.48, normalText: 'Fail', largeText: 'AA' }
checkContrast('#999', '#fff');
// { ratio: 2.85, normalText: 'Fail', largeText: 'Fail' }Color Suggestion
import { suggestForeground } from '@siluat/color-contrast';
suggestForeground('#777', '#fff', 4.5);
// { suggested: '#767676', result: { ratio: 4.54, normalText: 'AA', largeText: 'AAA' } }
suggestForeground('#333', '#fff', 4.5);
// { suggested: null, result: null } (already passes)Returns a SuggestResult with the closest foreground color meeting the target ratio. The suggested and result fields are null when the pair already passes or no solution exists.
Color Validation
Validate both colors upfront and collect all errors at once, instead of failing on the first invalid color:
import { validateColors } from '@siluat/color-contrast';
validateColors('#000', '#fff'); // []
validateColors('#gg0000', '#zz0000');
// [
// 'Invalid color: "#gg0000"\n Hex colors use characters 0-9 and a-f. Example: #ff0000',
// 'Invalid color: "#zz0000"\n Hex colors use characters 0-9 and a-f. Example: #ff0000',
// ]Error Handling
Both contrastRatio and checkContrast throw an Error for invalid color strings:
contrastRatio('not-a-color', '#fff');
// Error: Invalid color: "not-a-color"
// Supported formats: #hex, named colors (red, blue, ...), rgb(), hsl(), ...
contrastRatio('#gg0000', '#fff');
// Error: Invalid color: "#gg0000"
// Hex colors use characters 0-9 and a-f. Example: #ff0000API Reference
type ComplianceLevel = 'AAA' | 'AA' | 'Fail';
interface ContrastResult {
ratio: number;
normalText: ComplianceLevel;
largeText: ComplianceLevel;
}
interface SuggestResult {
suggested: string | null;
result: ContrastResult | null;
}
function contrastRatio(foreground: string, background: string): number;
function checkContrast(foreground: string, background: string): ContrastResult;
function suggestForeground(foreground: string, background: string, targetRatio: number): SuggestResult;
function validateColors(foreground: string, background: string): string[];ratio is rounded to 2 decimal places. Range is 1 to 21.
WCAG 2.1 compliance thresholds:
| Level | Normal text | Large text | |-------|-------------|------------| | AAA | >= 7 | >= 4.5 | | AA | >= 4.5 | >= 3 |
Supported Color Formats
- HEX:
#RGB,#RRGGBB,#RGBA,#RRGGBBAA - Named colors:
red,navy,rebeccapurple,transparent(148 named colors) - RGB:
rgb(255 0 0),rgb(255 0 0 / 0.5),rgba(255, 0, 0, 0.5) - HSL:
hsl(120 100% 50%),hsl(120 100% 50% / 0.5),hsla(120, 100%, 50%, 0.5) - HWB:
hwb(120 0% 0%),hwb(120 0% 0% / 0.5) - LAB:
lab(50% 40 59.5),lab(50% 40 59.5 / 0.5) - LCH:
lch(52.2% 72.2 50),lch(52.2% 72.2 50 / 0.5) - OKLAB:
oklab(59% 0.1 0.1),oklab(59% 0.1 0.1 / 0.5) - OKLCH:
oklch(60% 0.15 50),oklch(60% 0.15 50 / 0.5)
How Alpha and Wide-Gamut Colors Are Handled
WCAG contrast ratio is defined between opaque sRGB colors. This library automatically resolves input colors to opaque sRGB before calculating contrast, matching what browsers actually render.
Alpha: Colors with alpha are composited to produce the opaque color users see on screen. Background is composited over white (browser default), then foreground is composited over the result.
contrastRatio('#00000080', '#ffffff'); // contrast of composited gray vs whiteWide-gamut colors: Colors in LAB, LCH, OKLAB, or OKLCH that fall outside the sRGB gamut are gamut-mapped using the CSS Color Level 4 algorithm (Section 13.2) — the same method browsers use to render these colors.
CLI
For command-line usage, see @siluat/color-contrast-cli.
