Jeff’s Color Contrast Analyzer

Analyze color contrast between multiple colors, up to colors total, in tons of formats. Hex, RGB and RGBA, HSL and HSLA, CSS Named Colors, HSB, HWB, Lab, LCH, Oklab, Oklch, and CMYK are fully supported. CSS syntax is also accepted color: #FFF or background-color: rgb(255, 0, 0);. More details and specifications are included in the help documentation.

from, calc(), and color() are not supported. Labels can be added to a color by placing the label before a colon, like link: #2C5491

Light Mode Colors
Dark Mode Colors
Contrast Method:

Too Many Colors

Only the first colors were processed. Please reduce the number of colors in your input.


Invalid Colors

The following colors could not be parsed.


Duplicate Colors

The following colors were entered more than once. Only the first occurrence was processed.


Equivalent Colors

The following colors represent the same values in different formats. Only the first occurrence was processed.

  • Original:
    Equivalent formats: ' . htmlspecialchars($duplicate) . ''; }, $group['duplicates'])) ?>

Too Many Colors

Only the first colors were processed in some modes. Please reduce the number of colors in your input.


Invalid Colors

Light mode - The following colors could not be parsed:

Dark mode - The following colors could not be parsed:


Duplicate Colors

The following colors were entered more than once. Only the first occurrence was processed.

Light mode:

Dark mode:


Equivalent Colors

The following colors represent the same values in different formats. Only the first occurrence was processed.

Light mode:

  • Original:
    Equivalent formats: ' . htmlspecialchars($duplicate) . ''; }, $group['duplicates'])) ?>

Dark mode:

  • Original:
    Equivalent formats: ' . htmlspecialchars($duplicate) . ''; }, $group['duplicates'])) ?>

Summary of Compatible Color Combinations ()

$bg): // Calculate all combinations for this background color $combinations = []; foreach ($parsed_colors as $fg_color => $fg) { if ($fg_color === $bg_color) continue; if ($current_method === 'wcag') { // Calculate luminance with alpha blending $fg_lum = getLuminance($fg['rgb'], $fg['alpha'], $bg['rgb']); $bg_lum = $bg['luminance']; $contrast = getContrastRatio($bg_lum, $fg_lum); $level = getWCAGLevel($contrast); if ($level !== 'Fail') { $combinations[] = [ 'color' => $fg_color, 'contrast' => $contrast, 'level' => $level ]; } } elseif ($current_method === 'apca') { // APCA calculations $contrast = getAPCAContrast($bg['rgb'], $fg['rgb'], $bg['alpha'], $fg['alpha']); $level = getAPCALevel($contrast); if (!str_contains($level, 'Fail')) { $combinations[] = [ 'color' => $fg_color, 'contrast' => $contrast, 'level' => $level ]; } } else { // both // Calculate both WCAG and APCA $fg_lum = getLuminance($fg['rgb'], $fg['alpha'], $bg['rgb']); $bg_lum = $bg['luminance']; $wcag_contrast = getContrastRatio($bg_lum, $fg_lum); $wcag_level = getWCAGLevel($wcag_contrast); $apca_contrast = getAPCAContrast($bg['rgb'], $fg['rgb'], $bg['alpha'], $fg['alpha']); $apca_level = getAPCALevel($apca_contrast); $combined_level = getCombinedLevel($wcag_contrast, $apca_contrast); if ($combined_level !== 'Fail') { $combinations[] = [ 'color' => $fg_color, 'wcag_contrast' => $wcag_contrast, 'apca_contrast' => $apca_contrast, 'level' => $combined_level ]; } } } if ($current_method === 'wcag') { // Group by WCAG level $wcag_groups = [ 'AAA' => [], 'AA' => [], 'AA Large' => [] ]; foreach ($combinations as $combo) { $wcag_groups[$combo['level']][] = $combo; } // Sort each group by contrast ratio foreach ($wcag_groups as &$group) { usort($group, function($a, $b) { return $b['contrast'] <=> $a['contrast']; }); } $has_valid_combinations = !empty($wcag_groups['AAA']) || !empty($wcag_groups['AA']) || !empty($wcag_groups['AA Large']); } elseif ($current_method === 'apca') { // Group by APCA level $apca_groups = [ 'Perfect' => [], 'Excellent' => [], 'Good' => [], 'Fair' => [] ]; foreach ($combinations as $combo) { $level_key = explode(' - ', $combo['level'])[0]; if (isset($apca_groups[$level_key])) { $apca_groups[$level_key][] = $combo; } } // Sort each group by absolute contrast value foreach ($apca_groups as &$group) { usort($group, function($a, $b) { return abs($b['contrast']) <=> abs($a['contrast']); }); } $has_valid_combinations = !empty($apca_groups['Perfect']) || !empty($apca_groups['Excellent']) || !empty($apca_groups['Good']) || !empty($apca_groups['Fair']); } else { // both // Group by combined level $combined_groups = [ 'Perfect' => [], 'Excellent' => [], 'Good' => [], 'Fair' => [] ]; foreach ($combinations as $combo) { if (isset($combined_groups[$combo['level']])) { $combined_groups[$combo['level']][] = $combo; } } // Sort each group by WCAG contrast ratio foreach ($combined_groups as &$group) { usort($group, function($a, $b) { return $b['wcag_contrast'] <=> $a['wcag_contrast']; }); } $has_valid_combinations = !empty($combined_groups['Perfect']) || !empty($combined_groups['Excellent']) || !empty($combined_groups['Good']) || !empty($combined_groups['Fair']); } ?>
Background AAA ≥ 7.0
Best
AA Normal ≥ 4.5
Second Best
AA Large ≥ 3.0
Third Best
Perfect ≥ 90 Excellent ≥ 75 Good ≥ 60 Fair ≥ 45 Perfect
WCAG ≥10 &
APCA ≥90
Excellent
WCAG ≥7 &
APCA ≥75
Good
WCAG ≥4.5 &
APCA ≥60
Fair
WCAG ≥3 &
APCA ≥45
 (Ratio: )
 (Lc: )
 () (Lc )
No valid color combinations found (all contrast ratios below 3.0) No valid color combinations found (all APCA values below 45) No valid color combinations found (failed both WCAG and APCA thresholds)

Complete Contrast Grid ()

$data): ?> $bg_data): ?> $fg_data): if ($current_method === 'wcag') { // Calculate luminance with alpha blending $fg_lum = getLuminance($fg_data['rgb'], $fg_data['alpha'], $bg_data['rgb']); $bg_lum = $bg_data['luminance']; $contrast = getContrastRatio($bg_lum, $fg_lum); $level = getWCAGLevel($contrast); $display_value = number_format($contrast, 2); } elseif ($current_method === 'apca') { // APCA calculations $contrast = getAPCAContrast($bg_data['rgb'], $fg_data['rgb'], $bg_data['alpha'], $fg_data['alpha']); $level = getAPCALevel($contrast); $display_value = number_format($contrast, 1); } else { // both // Calculate both WCAG and APCA $fg_lum = getLuminance($fg_data['rgb'], $fg_data['alpha'], $bg_data['rgb']); $bg_lum = $bg_data['luminance']; $wcag_contrast = getContrastRatio($bg_lum, $fg_lum); $wcag_level = getWCAGLevel($wcag_contrast); $apca_contrast = getAPCAContrast($bg_data['rgb'], $fg_data['rgb'], $bg_data['alpha'], $fg_data['alpha']); $apca_level = getAPCALevel($apca_contrast); $combined_level = getCombinedLevel($wcag_contrast, $apca_contrast); } ?>
BG \ FG
Sample

Lc 
() (Lc )

Light Mode Results

Summary of Compatible Color Combinations ()

$bg): // Calculate all combinations for this background color $combinations = []; foreach ($fg_colors as $fg_color => $fg) { if ($current_method === 'wcag') { // Calculate luminance with alpha blending $fg_lum = getLuminance($fg['rgb'], $fg['alpha'], $bg['rgb']); $bg_lum = $bg['luminance']; $contrast = getContrastRatio($bg_lum, $fg_lum); $level = getWCAGLevel($contrast); if ($level !== 'Fail') { $combinations[] = [ 'color' => $fg_color, 'contrast' => $contrast, 'level' => $level ]; } } elseif ($current_method === 'apca') { // APCA calculations $contrast = getAPCAContrast($bg['rgb'], $fg['rgb'], $bg['alpha'], $fg['alpha']); $level = getAPCALevel($contrast); if (!str_contains($level, 'Fail')) { $combinations[] = [ 'color' => $fg_color, 'contrast' => $contrast, 'level' => $level ]; } } else { // both // Calculate both WCAG and APCA $fg_lum = getLuminance($fg['rgb'], $fg['alpha'], $bg['rgb']); $bg_lum = $bg['luminance']; $wcag_contrast = getContrastRatio($bg_lum, $fg_lum); $wcag_level = getWCAGLevel($wcag_contrast); $apca_contrast = getAPCAContrast($bg['rgb'], $fg['rgb'], $bg['alpha'], $fg['alpha']); $apca_level = getAPCALevel($apca_contrast); $combined_level = getCombinedLevel($wcag_contrast, $apca_contrast); if ($combined_level !== 'Fail') { $combinations[] = [ 'color' => $fg_color, 'wcag_contrast' => $wcag_contrast, 'apca_contrast' => $apca_contrast, 'level' => $combined_level ]; } } } if ($current_method === 'wcag') { // Group by WCAG level $wcag_groups = [ 'AAA' => [], 'AA' => [], 'AA Large' => [] ]; foreach ($combinations as $combo) { $wcag_groups[$combo['level']][] = $combo; } // Sort each group by contrast ratio foreach ($wcag_groups as &$group) { usort($group, function($a, $b) { return $b['contrast'] <=> $a['contrast']; }); } $has_valid_combinations = !empty($wcag_groups['AAA']) || !empty($wcag_groups['AA']) || !empty($wcag_groups['AA Large']); } elseif ($current_method === 'apca') { // Group by APCA level $apca_groups = [ 'Perfect' => [], 'Excellent' => [], 'Good' => [], 'Fair' => [] ]; foreach ($combinations as $combo) { $level_key = explode(' - ', $combo['level'])[0]; if (isset($apca_groups[$level_key])) { $apca_groups[$level_key][] = $combo; } } // Sort each group by absolute contrast value foreach ($apca_groups as &$group) { usort($group, function($a, $b) { return abs($b['contrast']) <=> abs($a['contrast']); }); } $has_valid_combinations = !empty($apca_groups['Perfect']) || !empty($apca_groups['Excellent']) || !empty($apca_groups['Good']) || !empty($apca_groups['Fair']); } else { // both // Group by combined level $combined_groups = [ 'Perfect' => [], 'Excellent' => [], 'Good' => [], 'Fair' => [] ]; foreach ($combinations as $combo) { if (isset($combined_groups[$combo['level']])) { $combined_groups[$combo['level']][] = $combo; } } // Sort each group by WCAG contrast ratio foreach ($combined_groups as &$group) { usort($group, function($a, $b) { return $b['wcag_contrast'] <=> $a['wcag_contrast']; }); } $has_valid_combinations = !empty($combined_groups['Perfect']) || !empty($combined_groups['Excellent']) || !empty($combined_groups['Good']) || !empty($combined_groups['Fair']); } ?>
Background AAA ≥ 7.0
Best
AA Normal ≥ 4.5
Second Best
AA Large ≥ 3.0
Third Best
Perfect ≥ 90 Excellent ≥ 75 Good ≥ 60 Fair ≥ 45 Perfect
WCAG ≥10 &
APCA ≥90
Excellent
WCAG ≥7 &
APCA ≥75
Good
WCAG ≥4.5 &
APCA ≥60
Fair
WCAG ≥3 &
APCA ≥45
 (Ratio: )
 (Lc: )
 () (Lc )
No valid color combinations found (all contrast ratios below 3.0) No valid color combinations found (all APCA values below 45) No valid color combinations found (failed both WCAG and APCA thresholds)

Complete Contrast Grid - Light Mode ()

$data): ?> $bg_data): ?> $fg_data): if ($current_method === 'wcag') { // Calculate luminance with alpha blending $fg_lum = getLuminance($fg_data['rgb'], $fg_data['alpha'], $bg_data['rgb']); $bg_lum = $bg_data['luminance']; $contrast = getContrastRatio($bg_lum, $fg_lum); $level = getWCAGLevel($contrast); $display_value = number_format($contrast, 2); } elseif ($current_method === 'apca') { // APCA calculations $contrast = getAPCAContrast($bg_data['rgb'], $fg_data['rgb'], $bg_data['alpha'], $fg_data['alpha']); $level = getAPCALevel($contrast); $display_value = number_format($contrast, 1); } else { // both // Calculate both WCAG and APCA $fg_lum = getLuminance($fg_data['rgb'], $fg_data['alpha'], $bg_data['rgb']); $bg_lum = $bg_data['luminance']; $wcag_contrast = getContrastRatio($bg_lum, $fg_lum); $wcag_level = getWCAGLevel($wcag_contrast); $apca_contrast = getAPCAContrast($bg_data['rgb'], $fg_data['rgb'], $bg_data['alpha'], $fg_data['alpha']); $apca_level = getAPCALevel($apca_contrast); $combined_level = getCombinedLevel($wcag_contrast, $apca_contrast); } ?>
BG \ FG
Sample

Lc 
() (Lc )

Dark Mode Results

Summary of Compatible Color Combinations ()

$bg): // Calculate all combinations for this background color $combinations = []; foreach ($fg_colors as $fg_color => $fg) { if ($current_method === 'wcag') { // Calculate luminance with alpha blending $fg_lum = getLuminance($fg['rgb'], $fg['alpha'], $bg['rgb']); $bg_lum = $bg['luminance']; $contrast = getContrastRatio($bg_lum, $fg_lum); $level = getWCAGLevel($contrast); if ($level !== 'Fail') { $combinations[] = [ 'color' => $fg_color, 'contrast' => $contrast, 'level' => $level ]; } } elseif ($current_method === 'apca') { // APCA calculations $contrast = getAPCAContrast($bg['rgb'], $fg['rgb'], $bg['alpha'], $fg['alpha']); $level = getAPCALevel($contrast); if (!str_contains($level, 'Fail')) { $combinations[] = [ 'color' => $fg_color, 'contrast' => $contrast, 'level' => $level ]; } } else { // both // Calculate both WCAG and APCA $fg_lum = getLuminance($fg['rgb'], $fg['alpha'], $bg['rgb']); $bg_lum = $bg['luminance']; $wcag_contrast = getContrastRatio($bg_lum, $fg_lum); $wcag_level = getWCAGLevel($wcag_contrast); $apca_contrast = getAPCAContrast($bg['rgb'], $fg['rgb'], $bg['alpha'], $fg['alpha']); $apca_level = getAPCALevel($apca_contrast); $combined_level = getCombinedLevel($wcag_contrast, $apca_contrast); if ($combined_level !== 'Fail') { $combinations[] = [ 'color' => $fg_color, 'wcag_contrast' => $wcag_contrast, 'apca_contrast' => $apca_contrast, 'level' => $combined_level ]; } } } if ($current_method === 'wcag') { // Group by WCAG level $wcag_groups = [ 'AAA' => [], 'AA' => [], 'AA Large' => [] ]; foreach ($combinations as $combo) { $wcag_groups[$combo['level']][] = $combo; } // Sort each group by contrast ratio foreach ($wcag_groups as &$group) { usort($group, function($a, $b) { return $b['contrast'] <=> $a['contrast']; }); } $has_valid_combinations = !empty($wcag_groups['AAA']) || !empty($wcag_groups['AA']) || !empty($wcag_groups['AA Large']); } elseif ($current_method === 'apca') { // Group by APCA level $apca_groups = [ 'Perfect' => [], 'Excellent' => [], 'Good' => [], 'Fair' => [] ]; foreach ($combinations as $combo) { $level_key = explode(' - ', $combo['level'])[0]; if (isset($apca_groups[$level_key])) { $apca_groups[$level_key][] = $combo; } } // Sort each group by absolute contrast value foreach ($apca_groups as &$group) { usort($group, function($a, $b) { return abs($b['contrast']) <=> abs($a['contrast']); }); } $has_valid_combinations = !empty($apca_groups['Perfect']) || !empty($apca_groups['Excellent']) || !empty($apca_groups['Good']) || !empty($apca_groups['Fair']); } else { // both // Group by combined level $combined_groups = [ 'Perfect' => [], 'Excellent' => [], 'Good' => [], 'Fair' => [] ]; foreach ($combinations as $combo) { if (isset($combined_groups[$combo['level']])) { $combined_groups[$combo['level']][] = $combo; } } // Sort each group by WCAG contrast ratio foreach ($combined_groups as &$group) { usort($group, function($a, $b) { return $b['wcag_contrast'] <=> $a['wcag_contrast']; }); } $has_valid_combinations = !empty($combined_groups['Perfect']) || !empty($combined_groups['Excellent']) || !empty($combined_groups['Good']) || !empty($combined_groups['Fair']); } ?>
Background AAA ≥ 7.0
Best
AA Normal ≥ 4.5
Second Best
AA Large ≥ 3.0
Third Best
Perfect ≥ 90 Excellent ≥ 75 Good ≥ 60 Fair ≥ 45 Perfect
WCAG ≥10 &
APCA ≥90
Excellent
WCAG ≥7 &
APCA ≥75
Good
WCAG ≥4.5 &
APCA ≥60
Fair
WCAG ≥3 &
APCA ≥45
 (Ratio: )
 (Lc: )
 () (Lc )
No valid color combinations found (all contrast ratios below 3.0) No valid color combinations found (all APCA values below 45) No valid color combinations found (failed both WCAG and APCA thresholds)

Complete Contrast Grid - Dark Mode ()

$data): ?> $bg_data): ?> $fg_data): if ($current_method === 'wcag') { // Calculate luminance with alpha blending $fg_lum = getLuminance($fg_data['rgb'], $fg_data['alpha'], $bg_data['rgb']); $bg_lum = $bg_data['luminance']; $contrast = getContrastRatio($bg_lum, $fg_lum); $level = getWCAGLevel($contrast); $display_value = number_format($contrast, 2); } elseif ($current_method === 'apca') { // APCA calculations $contrast = getAPCAContrast($bg_data['rgb'], $fg_data['rgb'], $bg_data['alpha'], $fg_data['alpha']); $level = getAPCALevel($contrast); $display_value = number_format($contrast, 1); } else { // both // Calculate both WCAG and APCA $fg_lum = getLuminance($fg_data['rgb'], $fg_data['alpha'], $bg_data['rgb']); $bg_lum = $bg_data['luminance']; $wcag_contrast = getContrastRatio($bg_lum, $fg_lum); $wcag_level = getWCAGLevel($wcag_contrast); $apca_contrast = getAPCAContrast($bg_data['rgb'], $fg_data['rgb'], $bg_data['alpha'], $fg_data['alpha']); $apca_level = getAPCALevel($apca_contrast); $combined_level = getCombinedLevel($wcag_contrast, $apca_contrast); } ?>
BG \ FG
Sample

Lc 
() (Lc )
1e9, 'millisecond' => 1e6, 'microsecond' => 1e3, 'nanosecond' => 1 ]; // Find the most appropriate unit $value = $nanoseconds; $unit = 'nanosecond'; foreach ($units as $name => $divisor) { if ($nanoseconds >= $divisor) { $value = $nanoseconds / $divisor; $unit = $name; break; } } // Format the output with appropriate pluralization $plural = $value != 1 ? 's' : ''; $seconds = $nanoseconds / 1e9; // Always show seconds as well if using a different unit if ($unit !== 'second') { echo sprintf("This code took %.6f seconds to execute, which is %.0f %s%s.", $seconds, $value, $unit, $plural); } else { echo sprintf("This code took %.6f seconds to execute.", $seconds); } ?>