Search code examples
javascriptcsscolorsrgbhsl

Obtain 50% of a color hex value without using transparency


I need to obtain the color value of a 50% lighter version of an existing color hex. However it has to be 100% opaque, I cannot use opacity, rgba, hexa or hsla.

The scenario:

I draw routes on a map, each one with a different color, based on a hardcoded array of 48 possible hex values.

When one of these routes is being edited it should be shown as "disabled" (50% of the original color).

In the screen design, the reference values were #9775fa for the route color (one of the colors in the array) and #d5c7fd for the disabled color. This second color was obtained by the designer drawing a white layer with 50% opacity on top of the base color.

I tried to obtain this same value via JS, first using a lighten function, then an HSL one and finally lightening manually each of the RGB values of the base color. None of them really worked.

Using lighten, adding 62 of light I got a near value, but not the exact one. Using HSL and lightening manually with 50% didn't work either.

These are the values I've got:

 Base color: #9775fa
 "Disabled color": #d5c7fd
 Lighten by 62: #d5b3ff
 HSL 50%: #e3b0ff
 Ligheting 50% by hand: #e3b0ff

So, by the end, the real question is, Is it possible to be achieved?

Here is a "playground" and the full code of my experiments (the second column is the reference "disabled" color.

Thanks a lot!


Solution

  • I managed to get more accurate results by mixing the color with white at your given percentage.

    I changed lightenByPercentage as follows:

    let p = percentage / 100;
    var r = "0x" + hex[0] + hex[1];
    var g = "0x" + hex[2] + hex[3];
    var b = "0x" + hex[4] + hex[5];
    r = Math.ceil(256 * (1-p) + (r * p));
    g = Math.ceil(256 * (1-p) + (g * p));
    b = Math.ceil(256 * (1-p) + (b * p));
    
    r = r <= 255 ? r : 255;
    g = g <= 255 ? g : 255;
    b = b <= 255 ? b : 255;
    

    I'm not sure if your percentage was supposed to be how light it is or how dark it is, so if I got it the wrong way around swap p with 1-p here.

    enter image description here