Created
November 10, 2020 23:55
-
-
Save avioli/b11813d43a8e5b795b38953f5d7ba3b3 to your computer and use it in GitHub Desktop.
A set of PHP functions to help get either white or black colour for foreground text over a given background
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Determine if a black or white foreground color will have a better contrast | |
* ratio for a given background color | |
* | |
* @param string|int $bg_r A hex representation of the color | |
* or the value of the red color 0-255 | |
* @param int $bg_g The value of the green color 0-255 | |
* @param int $bg_b The value of the blue color 0-255 | |
* | |
* @return string|array Either `#ffffff` or `#000000` if $bg_r was a string, | |
* otherwise `[255, 255, 255]` or `[0, 0, 0]` | |
*/ | |
function foreground_color($bg_r, $bg_g = null, $bg_b = null) { | |
$is_string = is_string($bg_r); | |
if ($is_string) { | |
list($bg_r, $bg_g, $bg_b) = hex_to_rgb($bg_r); | |
} | |
$contrast = get_contrast($bg_r, $bg_g, $bg_b, 255, 255, 255); | |
if ($contrast >= 4.5) { | |
$result = [255, 255, 255]; | |
} else { | |
$result = [0, 0, 0]; | |
} | |
if ($is_string) { | |
$result = array_map('dechex', $result); | |
$result = array_map(function ($v) { return strlen($v) == 1 ? "{$v}{$v}" : $v; }, $result); | |
return '#' . implode('', $result); | |
} | |
return $result; | |
} | |
/** | |
* Compute contrast ratio between two colors according to WCAG 2.0 AA and AAA | |
* levels | |
* | |
* A result between: | |
* - 0 and 3 means there is not enough contrast, thus fails WCAG 2.0 test | |
* - 3 and 4.5 means it passes AA level only for large text (above 18pt or | |
* bold above 14pt) | |
* - 4.5 and 7 means it passes AA level for any size text and AAA only for | |
* large text (above 18pt or bold above 14pt) | |
* - 7 and 22 means it passes AAA level for any size text | |
* | |
* @param int $r1 The value of the first colours' red 0-255 | |
* @param int $g1 The value of the first colours' green 0-255 | |
* @param int $b1 The value of the first colours' blue 0-255 | |
* @param int $r2 The value of the second colours' red 0-255 | |
* @param int $g2 The value of the second colours' green 0-255 | |
* @param int $b2 The value of the second colours' blue 0-255 | |
* | |
* @return int The contrast ratio between two colours | |
*/ | |
function get_contrast($r1, $g1, $b1, $r2, $g2, $b2) { | |
$lum1 = get_luminance($r1, $g1, $b1); | |
$lum2 = get_luminance($r2, $g2, $b2); | |
$ratio = ($lum1 + 0.05) / ($lum2 + 0.05); | |
if ($lum2 > $lum1) { | |
$ratio = 1 / $ratio; | |
} | |
return $ratio; | |
} | |
/** | |
* Compute the relative luminance - the relative brightness of any point in a | |
* colorspace, normalized to 0 for darkest black and 1 for lightest white | |
* | |
* @param int $r The value of the red colour 0-255 | |
* @param int $g The value of the green colour 0-255 | |
* @param int $b The value of the blue colour 0-255 | |
* | |
* @return int The relative luminance of given colour | |
*/ | |
function get_luminance($r, $g, $b) { | |
$rgb = [$r, $g, $b]; | |
foreach ($rgb as $key => $val) { | |
$val = $val / 255; | |
$val = $val < 0.03928 ? $val / 12.92 : pow(($val + 0.055) / 1.055, 2.4); | |
$rgb[$key] = $val; | |
} | |
return 0.2126 * $rgb[0] + 0.7152 * $rgb[1] + 0.0722 * $rgb[2]; | |
} | |
/** | |
* Convert a HEX color to a RGB array | |
* | |
* Both #RGB and #RRGGBB formats are supported, while # is optional. | |
* | |
* @param string $hex_color A hex color | |
* | |
* @return array|FALSE An [int, int, int] array or FALSE if format is incorrect. | |
*/ | |
function hex_to_rgb($hex_color) { | |
$hex_color = trim($hex_color, '#'); | |
$len = strlen($hex_color); | |
if ($len == 3) { | |
return array_map(function ($v) { return hexdec("{$v}{$v}"); }, str_split($hex_color)); | |
} else if ($len == 6) { | |
return array_map('hexdec', str_split($hex_color, 2)); | |
} | |
return FALSE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment