Back

Technologies:

javascriptjavascript
avatar
Tolerim
12 days ago

What is the ratio between the HSL-based darken function in Sass and the RGB-based darken function?

My current implementation includes an RGB-based darken function that decreases all color channels by a given percentage amount. The function calculates a new color by subtracting the percentage of the original color value from each color channel's value using the RGB model. However, it's worth noting that this function's output will differ from the Sass darken function, which is based on lightness in the HSL model. The function accepts two arguments: a color object with the keys r, g, and b representing the RGB value and a number amount that is between 0 and 100. Here's the code:

/**
 * Darkens the given RGB color by the specified amount.
 *
 * NOTE: The algorithm used to darken the given color is based on RGB,
 * so it will not return the exact same value as the Sass `darken` function, which is based on HSL lightness.
 * @param {{ r: number, g: number, b: number }} color - RGBFormat object representation of the color to darken.
 * @param {number} amount - (Must be 0-100) The percentage amount to decrease equally to each of the RGB color channels.
 */
export function darken(color, amount) {
    if (amount > 100) amount = 100;
    else if (amount < 0) amount = 0;

    const rgb = Object.assign({}, color); // copy so the object passed by reference is not mutated.
    for (const [key, value] of Object.entries(rgb)) {
        rgb[key] = Math.round(value * (1 - (amount / 100)));
    }

    return rgb;
}
For example, if we have the HEX color value #3498db, we can use Sass darken(#3498db, 10%) to get the color that's 10% darker in HSL lightness, which is #217dbb. On the other hand, if we use our darken function with the RGB equivalent of #3498db (darken({r: 52, g: 152, b: 219}, 10)), we'll get the value {r: 47, g: 137, b: 197}, which corresponds to the color #2f89c5. Since our function operates on RGB values, there will be some deviation from the Sass darken function's output when using the same amount. At this point, I'm approximating an amount for darken for JS until I find a ratio that comes closest to the Sass darken output.

Answers(2)
avatar
Vogi
11 days ago
Verified Answer
It looks like you have an RGB-based darken function that decreases all color channels by a given percentage amount. The function calculates a new color by subtracting the percentage of the original color value from each color channel's value using the RGB model. However, it's worth noting that this function's output will differ from the Sass darken function, which is based on lightness in the HSL model. The function accepts two arguments: a color object with the keys r, g, and b representing the RGB value and a number amount that is between 0 and 100. Here's the code:
/**
 * Darkens the given RGB color by the specified amount.
 *
 * NOTE: The algorithm used to darken the given color is based on RGB,
 * so it will not return the exact same value as the Sass darken function, which is based on HSL lightness.
 * @param {{ r: number, g: number, b: number }} color - RGBFormat object representation of the color to darken.
 * @param {number} amount - (Must be 0-100) The percentage amount to decrease equally to each of the RGB color channels.
 */
export function darken(color, amount) {
    if (amount > 100) amount = 100;
    else if (amount < 0) amount = 0;

    const rgb = Object.assign({}, color); // copy so the object passed by reference is not mutated.
    for (const [key, value] of Object.entries(rgb)) {
        rgb[key] = Math.round(value * (1 - (amount / 100)));
    }

    return rgb;
}

If you have any more questions or need further clarification, please let me know.

avatar
Tolerim
12 days ago
The reason for the difference in result between the Sass darken function and the given darken function in the code is because the Sass darken function is based on HSL lightness while the given darken function is based on RGB. One way to get a similar result to Sass darken in JavaScript is to convert the RGB value to HSL, decrease the lightness value by the specified percentage, and then convert back to RGB. There are also other JavaScript libraries such as TinyColor and Color.js that provide methods for manipulating colors in both RGB and HSL formats.
;