stylus icon indicating copy to clipboard operation
stylus copied to clipboard

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

Open Personwithhat opened this issue 4 years ago • 3 comments

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

Personwithhat avatar Aug 12 '21 20:08 Personwithhat

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.

Gusted avatar Aug 12 '21 20:08 Gusted

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

image

  • The upper gradient ramp is reduced by 20px, which is allocated for the contrast info
  • Clicking the big background swatch would switch the UI into setting the background color.
  • Clicking the inner swatch would switch it back
  • Clicking ? above would show this info (all translatable)
  • Clicking Type it allows typing a text there

tophf avatar Aug 13 '21 06:08 tophf

That looks great actually!

Personwithhat avatar Aug 13 '21 17:08 Personwithhat