/// @group functions
////
-/// Checks the lightness of `$color`, and if it passes the `$threshold` of lightness, it returns the `$yes` color. Otherwise, it returns the `$no` color. Use this function to dynamically output a foreground color based on a given background color.
+/// Checks the luminance of `$color`.
///
-/// @param {Color} $color - Color to check the lightness of.
-/// @param {Color} $yes [$black] - Color to return if `$color` is light.
-/// @param {Color} $no [$white] - Color to return if `$color` is dark.
-/// @param {Percentage} $threshold [60%] - Threshold of lightness to check against.
+/// @param {Color} $color - Color to check the luminance of.
///
-/// @returns {Color} The $yes color or $no color.
-@function foreground($color, $yes: $black, $no: $white, $threshold: 60%) {
- @if $color == transparent {
- $color: $body-background;
+/// @returns {Number} The luminance of `$color`.
+@function color-luminance($color) {
+ // Adapted from: https://github.com/LeaVerou/contrast-ratio/blob/gh-pages/color.js
+ // Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+ $rgba: red($color), green($color), blue($color);
+ $rgba2: ();
+
+ @for $i from 1 through 3 {
+ $rgb: nth($rgba, $i);
+ $rgb: $rgb / 255;
+
+ $rgb: if($rgb < 0.03928, $rgb / 12.92, pow(($rgb + 0.055) / 1.055, 2.4));
+
+ $rgba2: append($rgba2, $rgb);
}
- @if (lightness($color) > $threshold) {
- @return $yes;
+
+ @return 0.2126 * nth($rgba2, 1) + 0.7152 * nth($rgba2, 2) + 0.0722 * nth($rgba2, 3);
+}
+
+/// Checks the contrast ratio of two colors.
+///
+/// @param {Color} $color1 - First color to compare.
+/// @param {Color} $color2 - Second color to compare.
+///
+/// @returns {Number} The contrast ratio of the compared colors.
+@function color-contrast($color1, $color2) {
+ // Adapted from: https://github.com/LeaVerou/contrast-ratio/blob/gh-pages/color.js
+ // Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
+ $luminance1: color-luminance($color1) + 0.05;
+ $luminance2: color-luminance($color2) + 0.05;
+ $ratio: $luminance1 / $luminance2;
+
+ @if $luminance2 > $luminance1 {
+ $ratio: 1 / $ratio;
}
- @else {
- @return $no;
+
+ $ratio: round($ratio * 10) / 10;
+
+ @return $ratio;
+}
+
+/// Checks the luminance of `$base`, and if it passes the `$threshold` of lightness, it returns the `$yes` color. Otherwise, it returns the `$no` color. Use this function to dynamically output a foreground color based on a given background color.
+///
+/// @param {Color} $color1 - First color to compare.
+/// @param {Color} $color2 - Second color to compare.
+///
+/// @returns {Number} The contrast ratio of the compared colors.
+@function pick-best-color($base, $colors: ($button-color, $button-color-alt), $tolerance: 0) {
+ $contrast: color-contrast($base, nth($colors, 1));
+ $best: nth($colors, 1);
+
+ @for $i from 2 through length($colors) {
+ $current-contrast: color-contrast($base, nth($colors, $i));
+ @if ($current-contrast - $contrast > $tolerance) {
+ $contrast: color-contrast($base, nth($colors, $i));
+ $best: nth($colors, $i);
+ }
}
+
+ @if ($contrast < 3) {
+ @warn "Contrast ratio of #{$best} on #{$base} is pretty bad, just #{$contrast}";
+ }
+
+ @return $best;
}
/// Scales a color to be darker if it's light, or lighter if it's dark. Use this function to tint a color appropriate to its lightness.