Skip to content

Instantly share code, notes, and snippets.

@xi
Created July 20, 2017 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xi/05d1fab7e6b054586f3e15021e76c861 to your computer and use it in GitHub Desktop.
Save xi/05d1fab7e6b054586f3e15021e76c861 to your computer and use it in GitHub Desktop.
flexible contrast function inspired by css-color-4
// This implements a flexible contrast function similar to the one
// proposed in <https://github.com/w3c/csswg-drafts/issues/1627>.
//
// Note that it uses some approximations and RGB instead of HWB
// interpolation.
@function srgb($channel) {
$x: $channel / 255;
@if $x <= .03928 {
@return $x / 12.92;
} @else {
$c: ($x + .055) / 1.055;
// approximation for pow($c, 2.4)
@return (133 * $c * $c * $c + 155 * $c * $c) / 288;
}
}
@function luminance($color) {
$r: srgb(red($color));
$g: srgb(green($color));
$b: srgb(blue($color));
@return .2126 * $r + .7152 * $g + .0722 * $b;
}
@function contrast($color1, $color2) {
$l1: luminance($color1);
$l2: luminance($color2);
@return (max($l1, $l2) + .05) / (min($l1, $l2) + .05);
}
@function interpolate($base, $lower, $upper, $value) {
$vlower: contrast($base, $lower);
$vupper: contrast($base, $upper);
@if $vlower > $vupper {
@return interpolate($base, $lower, $upper, $value);
}
@if $vlower >= $value {
@return $lower;
}
@if $vupper <= $value {
@return $upper;
}
$color: null;
@for $i from 0 to 10 {
$color: mix($lower, $upper);
@if contrast($color, $base) < $value {
$lower: $color;
} @else {
$upper: $color;
}
}
@return $color;
}
@function contrast-color($base, $candidates: (), $amount: 100%) {
$lbase: luminance($base);
$color: $base;
$highscore: 0;
@each $candidate in $candidates {
$contrast: contrast($base, $candidate);
$luminance: luminance($candidate);
@if $contrast >= 4.5 {
@return $candidate;
} @else if $contrast > $highscore and if($lbase < .18, $luminance > $lbase, $luminance < $lbase) {
$highscore: $contrast;
$color: $candidate;
}
}
$max: if($lbase < .18, white, black);
$min: interpolate($base, $color, $max, 4.5);
@return mix($min, $max, 100% - $amount);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment