Color Blindness Simulator - Test Color Accessibility Online
Simulate how colors appear to people with protanopia, deuteranopia, and tritanopia. Check WCAG contrast ratios for accessible web design.
Frequently Asked Questions
What is a Color Blindness Simulator?
A color blindness simulator is an online tool that shows how colors and images appear to people with color vision deficiency (CVD). It applies scientifically-validated algorithms to transform colors, helping designers and developers understand how their visual content is perceived by approximately 8% of males and 0.5% of females who have some form of color blindness.
How do I use this tool?
This tool has two modes. Color Mode: enter foreground and background colors using HEX values, RGB values, or the color picker, and the tool instantly shows how these colors appear under all 8 types of color vision deficiency along with WCAG contrast ratios. Image Mode: upload an image (drag-and-drop or file browse), select a CVD type, and see the simulated version side-by-side with the original. You can download the simulated image for documentation or presentations.
Is my data safe? Does it get sent to a server?
Your data is 100% safe and never leaves your browser. All color calculations, WCAG contrast checking, and image processing are performed entirely client-side using JavaScript and the Canvas API. No colors or images are transmitted to any server, making this tool safe for testing proprietary designs, confidential brand assets, and sensitive visual content.
What are the 8 types of color vision deficiency?
The 8 types are: Protanopia (no red cones, reds appear dark), Deuteranopia (no green cones, most common dichromacy), Tritanopia (no blue cones, blue-yellow confusion), Protanomaly (reduced red sensitivity, reds appear weaker), Deuteranomaly (reduced green sensitivity, the most common CVD affecting ~5% of males), Tritanomaly (reduced blue sensitivity, very rare), Achromatopsia (complete color blindness, sees only grayscale), and Achromatomaly (partial color blindness, severely reduced color perception).
How does the WCAG contrast checker work with color blindness simulation?
The tool calculates the standard WCAG 2.1 contrast ratio between your foreground and background colors, then recalculates the contrast after applying each CVD simulation. This reveals cases where a color pair passes WCAG standards for normal vision but fails for people with color vision deficiency -- a critical insight for truly accessible design.
What simulation algorithms does this tool use?
This tool uses peer-reviewed, scientifically-validated algorithms: Brettel, Vienot & Mollon (1997) for dichromacy types (Protanopia, Deuteranopia, Tritanopia) and Machado, Oliveira & Fernandes (2009) for anomalous trichromacy types (Protanomaly, Deuteranomaly, Tritanomaly). Achromatopsia uses ITU-R BT.709 luminance weighting. All transformations are performed in linear RGB color space for accuracy.
Can I test images with this tool?
Yes. The Image tab allows you to upload images (JPG, PNG, WebP, GIF) up to 4096x4096 pixels. The tool uses the Canvas API to apply pixel-level CVD simulation, showing the original and simulated images side-by-side. You can download the simulated image for use in accessibility audits or documentation.
What is the difference between -anopia and -anomaly types?
The suffix "-anopia" means complete absence of a cone type (dichromacy), while "-anomaly" means reduced sensitivity (anomalous trichromacy). For example, Protanopia means no red cones at all, while Protanomaly means red cones are present but shifted in sensitivity. Anomaly types are generally milder and more common than anopia types.
Code Examples
// Color Blindness Simulator - JavaScript Implementation
/**
* sRGB to Linear RGB conversion
*/
function srgbToLinear(c) {
const v = c / 255;
return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
}
function linearToSrgb(c) {
const v = Math.max(0, Math.min(1, c));
return Math.round(
(v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055) * 255
);
}
/**
* CVD simulation matrices (Brettel 1997 / Machado 2009)
* Each is a 3x3 matrix stored as flat array [row-major]
*/
const CVD_MATRICES = {
protanopia: [
0.152286, 1.052583, -0.204868,
0.114503, 0.786281, 0.099216,
-0.003882, -0.048116, 1.051998,
],
deuteranopia: [
0.367322, 0.860646, -0.227968,
0.280085, 0.672501, 0.047413,
-0.011820, 0.042940, 0.968881,
],
tritanopia: [
1.255528, -0.076749, -0.178779,
-0.078411, 0.930809, 0.147602,
0.004733, 0.691367, 0.303900,
],
achromatopsia: [
0.2126, 0.7152, 0.0722,
0.2126, 0.7152, 0.0722,
0.2126, 0.7152, 0.0722,
],
};
/**
* Simulate color vision deficiency for a single RGB color
* @param {number} r - Red (0-255)
* @param {number} g - Green (0-255)
* @param {number} b - Blue (0-255)
* @param {string} cvdType - CVD type key
* @param {number} severity - 0.0 to 1.0
* @returns {number[]} Simulated [r, g, b]
*/
function simulateColor(r, g, b, cvdType, severity = 1.0) {
const matrix = CVD_MATRICES[cvdType];
if (!matrix) throw new Error(`Unknown CVD type: ${cvdType}`);
// Convert to linear
const lr = srgbToLinear(r);
const lg = srgbToLinear(g);
const lb = srgbToLinear(b);
// Apply matrix
const sr = matrix[0] * lr + matrix[1] * lg + matrix[2] * lb;
const sg = matrix[3] * lr + matrix[4] * lg + matrix[5] * lb;
const sb = matrix[6] * lr + matrix[7] * lg + matrix[8] * lb;
// Lerp with original for severity
const fr = lr * (1 - severity) + sr * severity;
const fg = lg * (1 - severity) + sg * severity;
const fb = lb * (1 - severity) + sb * severity;
return [linearToSrgb(fr), linearToSrgb(fg), linearToSrgb(fb)];
}
/**
* Calculate WCAG 2.1 contrast ratio
*/
function getContrastRatio(fg, bg) {
const lum = (r, g, b) =>
0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
const l1 = lum(...fg);
const l2 = lum(...bg);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
/**
* Check WCAG compliance
*/
function checkWCAG(ratio) {
return {
aa: { normalText: ratio >= 4.5, largeText: ratio >= 3 },
aaa: { normalText: ratio >= 7, largeText: ratio >= 4.5 },
};
}
// Usage
const fg = [255, 102, 0]; // Orange
const bg = [255, 255, 255]; // White
console.log("Original contrast:", getContrastRatio(fg, bg).toFixed(2) + ":1");
const cvdTypes = ["protanopia", "deuteranopia", "tritanopia", "achromatopsia"];
for (const type of cvdTypes) {
const simFg = simulateColor(...fg, type);
const simBg = simulateColor(...bg, type);
const ratio = getContrastRatio(simFg, simBg);
const wcag = checkWCAG(ratio);
console.log(`${type}: ${ratio.toFixed(2)}:1 (AA: ${wcag.aa.normalText ? "PASS" : "FAIL"})`);
}