|
@function is-color($color) { |
|
@if (type-of($color) == color) { |
|
@return true; |
|
} |
|
@return false; |
|
} |
|
|
|
@function count-occurrences($string, $search) { |
|
$searchIndex: str-index($string, $search); |
|
$searchCount: 0; |
|
@while $searchIndex { |
|
$searchCount: $searchCount + 1; |
|
$string: str-slice($string, $searchIndex + 1); |
|
$searchIndex: str-index($string, $search); |
|
} |
|
@return $searchCount; |
|
} |
|
|
|
@function str-is-between($string, $first, $last) { |
|
$firstCount: count-occurrences($string, $first); |
|
$lastCount: count-occurrences($string, $last); |
|
@return $firstCount == $lastCount; |
|
} |
|
|
|
@function recursive-color($color, $index: 0) { |
|
$indices: ( |
|
0: h, |
|
1: s, |
|
2: l, |
|
3: a |
|
); |
|
// find end of part |
|
$end: str-index($color, ','); |
|
@while ($end and not str-is-between(str-slice($color, 0, $end - 1), '(', ')')) { |
|
$newEnd: str-index(str-slice($color, $end + 1), ','); |
|
@if (not $newEnd) { |
|
$newEnd: 0; |
|
} |
|
$end: 2 + $end + $newEnd; |
|
} |
|
@if ($end) { |
|
$part: str-slice($color, 0, $end - 1); |
|
$value: map-merge( |
|
( |
|
map-get($indices, $index): $part |
|
), |
|
recursive-color(str-slice($color, $end + 1), $index + 1) |
|
); |
|
@return $value; |
|
} |
|
@return (); |
|
} |
|
|
|
@function to-hsl($color) { |
|
$c: inspect($color); |
|
|
|
$h: 0; |
|
$s: 0; |
|
$l: 0; |
|
$a: 1; |
|
|
|
@if (is-color($color)) { |
|
// std color |
|
$h: hue($color); |
|
$s: saturation($color); |
|
$l: lightness($color); |
|
$a: alpha($color); |
|
|
|
@return (h: $h, s: $s, l: $l, a: $a); |
|
} |
|
|
|
@if (str-slice($c, 0, 3) == 'var') { |
|
// var(--color) |
|
$commaPos: str-index($c, ','); |
|
$end: -2; |
|
@if ($commaPos) { |
|
$end: $commaPos - 1; |
|
} |
|
$var: str-slice($c, 7, $end); |
|
|
|
$h: var(--#{$var}-h); |
|
$s: var(--#{$var}-s); |
|
$l: var(--#{$var}-l); |
|
$a: var(--#{$var}-a, 1); |
|
|
|
@return (h: $h, s: $s, l: $l, a: $a); |
|
} |
|
|
|
@if ($c == '0') { |
|
@return (h: $h, s: $s, l: $l, a: $a); |
|
} |
|
|
|
// color is (maybe complex) calculated color |
|
// e.g.: hsla(calc((var(--white-h) + var(--primary-h)) / 2), calc((var(--white-s) + var(--primary-s)) / 2), calc((var(--white-l) + var(--primary-l)) / 2), calc((var(--white-a, 1) + var(--primary-a, 1)) / 2)), hsla(calc((var(--white-h) + var(--primary-h)) / 2), calc((var(--white-s) + var(--primary-s)) / 2), calc((var(--white-l) + var(--primary-l)) / 2), calc((var(--white-a, 1) + var(--primary-a, 1)) / 2)) |
|
$startPos: str-index($c, '('); |
|
$c: str-slice($c, $startPos + 1, -2); // 3 or 4 comma-separated vomplex values |
|
@return recursive-color($c); |
|
// $hEnd: str-index($c, ','); |
|
// @if ($hEnd) { |
|
// $h: str-slice($c, 0, $hEnd - 1); |
|
// $c: str-slice($c, $hEnd + 1); |
|
// $sEnd: str-index($c, ','); |
|
// @if ($hEnd) { |
|
// $h: str-slice($c, 0, $hEnd - 1); |
|
// $c: str-slice($c, $hEnd + 1); |
|
// $sEnd: str-index($c, ','); |
|
// } |
|
// } |
|
|
|
// @return (h: $h, s: $s, l: $l, a: $a); |
|
} |
|
|
|
@function render-hsla($h, $s, $l, $a: 1) { |
|
@return hsla($h, $s, $l, $a); |
|
} |
|
|
|
@function lighten($color, $amount) { |
|
@if (is-color($color)) { |
|
@return scale-color($color: $color, $lightness: $amount); |
|
} |
|
|
|
$c: to-hsl($color); |
|
$h: map-get($c, h); |
|
$s: map-get($c, s); |
|
$l: map-get($c, l); |
|
$a: map-get($c, a); |
|
@return render-hsla($h, $s, calc(#{$l} + #{$amount}), $a); |
|
} |
|
|
|
@function darken($color, $amount) { |
|
@return lighten($color, $amount * -1); |
|
} |
|
|
|
@function rgba($red, $green, $blue: false, $alpha: false) { |
|
$color: $red; |
|
|
|
@if (not $blue and not $alpha) { |
|
$alpha: $green; |
|
$color: $red; |
|
} |
|
|
|
$c: to-hsl($color); |
|
$h: map-get($c, h); |
|
$s: map-get($c, s); |
|
$l: map-get($c, l); |
|
@return render-hsla($h, $s, $l, $alpha); |
|
} |
|
|
|
@function rgb($red, $green, $blue) { |
|
@return rgba($red, $green, $blue, 1); |
|
} |
|
|
|
@function mix($color-1, $color-2, $weight: 50%) { |
|
$c1: to-hsl($color-1); |
|
$c2: to-hsl($color-2); |
|
|
|
$h1: map-get($c1, h); |
|
$s1: map-get($c1, s); |
|
$l1: map-get($c1, l); |
|
$a1: map-get($c1, a); |
|
|
|
$h2: map-get($c2, h); |
|
$s2: map-get($c2, s); |
|
$l2: map-get($c2, l); |
|
$a2: map-get($c2, a); |
|
|
|
$h: calc((#{$h1} + #{$h2}) / 2); |
|
$s: calc((#{$s1} + #{$s2}) / 2); |
|
$l: calc((#{$l1} + #{$l2}) / 2); |
|
$a: calc((#{$a1} + #{$a2}) / 2); |
|
|
|
@return render-hsla($h, $s, $l, $a); |
|
} |
|
|
|
@function fade-in($color, $amount) { |
|
$c: to-hsl($color); |
|
|
|
$h: map-get($c, h); |
|
$s: map-get($c, s); |
|
$l: map-get($c, l); |
|
$a: map-get($c, a); |
|
@if (not $a) { |
|
$a: 1; |
|
} |
|
|
|
@return render-hsla($h, $s, $l, $a + $amount); |
|
} |
|
|
|
@function color-yiq($color, $dark: $yiq-text-dark, $light: $yiq-text-light) { |
|
@if (is-color($color)) { |
|
$r: red($color); |
|
$g: green($color); |
|
$b: blue($color); |
|
|
|
$yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000; |
|
|
|
@if ($yiq >= $yiq-contrasted-threshold) { |
|
@return $dark; |
|
} @else { |
|
@return $light; |
|
} |
|
} @else { |
|
$c: to-hsl($color); |
|
$l: map-get($c, l); |
|
|
|
$th: $yiq-contrasted-threshold / 2.56; // convert hex to dec |
|
$lightness: calc(-100 * calc(#{$l} - #{$th * 1%})); |
|
|
|
// ignoring hue and saturation, just a light or dark gray |
|
@return render-hsla(0, 0%, $lightness, 1); |
|
} |
|
} |
@R-Iqbal
primary-h
,primary-s
andprimary-l
are the hue, saturation and lightness of the color I namedprimary
, e.g. the main color of your brand. The values can be set manually (hardcoded) as shown in the html file, or generated from javascript as seen in the jsx file where I wrote the functionApplyBranding
to convert color values to css 'custom properties'.Example:
… will generate this style element in your html …
… which is necessary to make the sass code work (to calculate the correct darken, lighten etc values).
→ So you can set the style values manually, or generate them with javascript, which was necessary in my project, since the colors were set externally, which was the main reason of creating this gist to start with.
I hope this helps?