sassscss-mixins

How can I convert a hex value to RGBA, while matching the original color


Given a color and alpha value, I am trying to create an SCSS function that converts a hex color to rgba color, but compensating for the perceived change in color. I.e. If the new color is "flattened" from rgba to rgb, you get the original input color.

examples

#F7F7F8 -> rgba(173, 181, 189,.1);

.c1-in{
 background:#F7F7F8;
}
.c1-out{
 background: rgba(173, 181, 189,.1);;
}
.c2-in{
 background:#C4DCD1;
}
.c2-out{
 background:rgb(21, 115, 71, .25);;
}
<div class="c1-in">color 1 in</div>
<div class="c1-out">color 1 out</div>
<div class="c2-in">color 2 in</div>
<div class="c2-out">color 2 out</div>

my attempt, not working

  @function toTrans($hex, $alpha) {
    $r: red($hex);
    $g: green($hex);
    $b: blue($hex);

    $new-r: ($r - (1 - $alpha) * 255) / $alpha;
    $new-g: ($g - (1 - $alpha) * 255) / $alpha;
    $new-b: ($b - (1 - $alpha) * 255) / $alpha;

    @return rgba(clamp($new-r, 0, 255), clamp($new-g, 0, 255), clamp($new-b, 0, 255), $alpha);
  }

Solution

  • here is the answer found in another post https://stackoverflow.com/a/38265284

    here is another answer I came up with

    @function transparentify($color, $a, $bg: #fff) {
     $r: red($color);
     $g: green($color);
     $b: blue($color);
    
     $r-bg: red($bg);
     $g-bg: green($bg);
     $b-bg: blue($bg);
    
     $a-r-min: calc(($r - $r-bg) / (-0.1 - $r-bg));
     $a-r-max: calc(($r - $r-bg) / (254.99 - $r-bg));
     @if ($a-r-min>$a-r-max) {
       $temp: $a-r-min;
       $a-r-min: $a-r-max;
       $a-r-max: -$temp;
     }
     $a-g-min: calc(($g - $g-bg) / (-0.1 - $g-bg));
     $a-g-max: calc(($g - $g-bg) / (254.99 - $g-bg));
     @if ($a-g-min>$a-g-max) {
       $temp: $a-g-min;
       $a-g-min: $a-g-max;
       $a-g-max: -$temp;
     }
     $a-b-min: calc(($b - $b-bg) / (-0.01 - $b-bg));
     $a-b-max: calc(($b - $b-bg) / (254.99 - $b-bg));
     @if ($a-b-min>$a-b-max) {
       $temp: $a-b-min;
       $a-b-min: $a-b-max;
       $a-b-max: -$temp;
     }
    
     $a-r-min: clamp(0, $a-r-min, 1);
     $a-r-max: clamp(0, $a-r-max, 1);
     $a-g-min: clamp(0, $a-g-min, 1);
     $a-g-max: clamp(0, $a-g-max, 1);
     $a-b-min: clamp(0, $a-b-min, 1);
     $a-b-max: clamp(0, $a-b-max, 1);
    
     $a-min: max($a-r-min, $a-g-min, $a-b-min);
     $a-max: min($a-r-max, $a-g-max, $a-b-max);
    
     // @debug alpha range $a_min to $a_max;
     @if ($a<$a-min or $a>$a-max) {
       @debug transparentify ERROR, alpha of $a is outside of range ($a_min to $a_max) for color $color on background $bg;
     }
    
     $r-new: calc(($r - $r-bg) / $a) + $r-bg;
     $g-new: calc(($g - $g-bg) / $a) + $g-bg;
     $b-new: calc(($b - $b-bg) / $a) + $b-bg;
    
     @return rgba($r-new, $g-new, $b-new, $a);
    }