openstyles / stylus

Stylus - Userstyles Manager
https://add0n.com/stylus.html
GNU General Public License v3.0
5.4k stars 304 forks source link

Feature Suggestion: Incorporate W3's SRGB contrast algorithm in color selection. #1310

Open Personwithhat opened 3 years ago

Personwithhat commented 3 years ago

The live-reload of colors is my favorite feature, haven't seen anything comparable in any other app I've used to date. Substantially speeds up color test iterations.

Right now I pick a decent color then have to switch to using Colorizer, contrast-ratio.com, etc., and go back/forth to repeat the process. Contrast is extremely important for working with colored text, as well as any scenarios where the colors need similar perceptual luminosity.

It would be nice if there was an additional string during color-pic that would post contrast when compared to a set background color. This would allow you to use the live-reload of colors to iterate while also making sure contrast ratios are within reasonable margins. Perhaps right above the color history rows?

W3's proposed algorithm uses the sRGB colorspace, it has a precision to the '5th decimal. A live example is here: https://contrast-ratio.com/#%23b97af7-on-%23030303

Gusted commented 3 years ago

proposed algorithm uses the sRGB colorspace, it has a precision to the '5th decimal. A live example is here: https://contrast-ratio.com/#%23b97af7-on-%23030303

coughs


/**
 * Calculate the Relative Luminance (RL) of a color.
 * Ref: https://www.w3.org/TR/WCAG/#dfn-relative-luminance
 * @param {{r: number, g: number, b: number}} color A RGB color.
 * @returns {number} The relative luminance of the color.
 */
function getRelativeLuminance(color) {
    const calculateLuminance = (value) => {
        value /= 255;
        if (value <= 0.03928) {
            return value / 12.92;
        }
        return ((value + 0.055) / 1.055) ** 2.4;
    };
    return 0.2126 * calculateLuminance(color.r) + 0.7152 * calculateLuminance(color.g) + 0.0722 * calculateLuminance(color.b);
}

/**
 * Calculate the contrast ratio between a foreground and a background color.
 * Ref: https://www.w3.org/TR/WCAG/#dfn-contrast-ratio
 * @param {{r: number, g: number, b: number}} fgColor A RGB color.
 * @param {{r: number, g: number, b: number}} bgColor A RGB color.
 * @returns {number} The contrast ratio of the foreground color to the background color.
 */
function getContrastRatio(fgColor, bgColor) {
    const fgLuminance = getRelativeLuminance(fgColor);
    const bgLuminance = getRelativeLuminance(bgColor);
    return (Math.max(fgLuminance, bgLuminance) + 0.05) / (Math.min(fgLuminance, bgLuminance) + 0.05);
}

That's the algorithm that W3c proposed via the sRGB color space. It return the precises relative luminance. Over at dark reader uses a slightly different approach but sRGB is reliable for a lot of colors.

tophf commented 3 years ago

Here's a UI mockup based on my understanding of the idea.

image

Personwithhat commented 3 years ago

That looks great actually!