Skip to content

Instantly share code, notes, and snippets.

@graygilmore
Last active February 4, 2021 16:30
Show Gist options
  • Save graygilmore/8d5e2b2dbc620804f33b to your computer and use it in GitHub Desktop.
Save graygilmore/8d5e2b2dbc620804f33b to your computer and use it in GitHub Desktop.
The goal of this Sass function is provide a hover color that works with any color on any background. No longer do we need to bundle hover color options with our themes, let Sassy McSasserson take care of that for you.
/*
The Ultimate Hover Color Function
@author Gray Gilmore - http://code.graygilmore.com
The goal of this Sass function is provide a hover color that works
with any color on any background. No longer do we need to bundle
hover color options with our themes, let Sassy McSasserson take care
of that for you.
The hover color, seen in this demo as "After" text, must be visible in
all situations and, hopefully, pass the WCAG 2.0 contrast ratio [1]
formula (4.5:1).
[1] http://www.w3.org/TR/2008/REC-WCAG20-20081211/#visual-audio-contrast-contrast
contrast-ratio() help from @davidkaneda
## Usage ##
a {
color: $link-color;
&:hover {
color: hover($background-color, $link-color);
}
}
button {
background: $button-background;
color: $button-color;
&:hover {
background: hover($background-color, $button-background);
}
}
## End Usage ##
*/
@function color-luminance($value) {
@if $value <= 0.03928 {
@return $value / 12.92;
} @else {
@return ($value + 0.055)/1.055 * ($value + 0.055)/1.055;
}
}
@function luminosity($color) {
$r: color-luminance(red($color) / 255);
$g: color-luminance(green($color) / 255);
$b: color-luminance(blue($color) / 255);
@return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
}
@function contrast-ratio($c1, $c2) {
$l1: luminosity($c1);
$l2: luminosity($c2);
@if $l2 > $l1 {
@return $l2 / $l1;
} @else {
@return $l1 / $l2;
}
}
@function hover($background, $color) {
$style: '';
$hover-color: '';
$color-lightness: abs(lightness($color));
$background-lightness: abs(lightness($background));
$contrast: abs(contrast-ratio($background, $color));
@if $color-lightness == 100 {
/* White */
@if $background-lightness >= 90 {
$hover-color: darken($background, 15);
} @else {
$hover-color: mix($color, $background, 80);
}
} @else if $color-lightness == 0 {
/* Black */
@if $background-lightness < 10 {
$hover-color: lighten($background, 20);
} @else {
$hover-color: mix($color, $background, 60);
}
} @else if $background-lightness < $color-lightness {
/* Light text on dark background */
$style: 'lighten';
@if $color-lightness > 90 {
/* Color too light to lighten */
$hover-color: darken($color, 20);
$style: 'darken';
} @else {
$hover-color: lighten($color, 20);
}
} @else {
/* Dark text on light background */
$style: 'darken';
@if $color-lightness < 15 {
/* Color is too dark to further darken */
$hover-color: lighten($color, 20);
$style: 'lighten';
} @else {
$hover-color: darken($color, 20);
}
}
/*
Sometimes the $hover-color won't have enough contrast
with the background. We'll try to fix this below by
increasing our darken/lighten range by +/- 5
*/
/* Only test if the $color isn't white or black */
@if $color-lightness != 0 and $color-lightness != 100 {
$new-contrast: contrast-ratio($background, $hover-color);
@if $new-contrast < 8 {
/* Test if we can find a color with a better contrast */
@for $i from 15 to 25 {
@if $style == 'darken' {
$test-color: darken($color, $i);
} @else {
$test-color: lighten($color, $i);
}
$test-contrast: contrast-ratio($background, $test-color);
@if $test-contrast > $new-contrast {
$new-contrast: $test-contrast;
$hover-color: $test-color;
}
}
}
}
@return $hover-color;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment