Re: [css-color] shifting a color to make adequate contrast with another color

On Mon, Mar 9, 2015 at 5:43 PM, Tab Atkins Jr. <jackalmage@gmail.com> wrote:
> On Fri, Mar 6, 2015 at 8:48 AM, Andrew VanWagoner
> <thetalecrafter@gmail.com> wrote:
>> As it is right now, the contrast() adjuster only makes a color from the base
>> color that contrasts with the base color. It would be much more useful to be
>> able to shift one color to make sure it contrasts with a separate color. And
>> the percentage is not so useful as explicitly providing the contrast ratio
>> you require.
>>
>> color(blue contrast(green 3)) would give you a blue-ish color that contrasts
>> with green at least 3:1.
>>
>> The use case I have for contrast is to make sure the foreground color
>> contrasts with the chosen background. I could target 3:1, 4.5:1, or 7:1
>> depending on the needs of the current user.
>
> I'd like to do this, but it's actually pretty hard to define.  The
> current definition is easy - just draw a line in RGB space between the
> background color and white/black, and then find the color you want
> there that hits the right contrast ratio.
>
> With two colors, it's less clear how to adjust the foreground color.
> Obviously targetting black/white as the "maximum contrast color" is
> still the correct answer, but then modifying the foreground color
> toward that might not monotonically increase contrast.  Take your
> example.  White is the maximum-contrast color for green, so if you
> wanted to adjust blue to 100% contrast, that's what you want to get.
> But if you draw a line from blue to white, the contrast from green
> actually goes *down* before it starts going up again.  (Specifically,
> the contrast ratio for blue vs green is about 1.7; as you blend blue
> into white, the ratio drops to about 1, then finally climbs back to
> 5.1 at full white.)
>
> We'd have to find the value on the blend line (from the foreground
> color to white/black) that's closest to the background color, as
> that'll be the point with minimum contrast, then decide which
> direction to head in to find the desired contrast.  Depending on the
> colors chosen, there may be *two* acceptable minimum-contrast colors;
> which should we choose?
>
> (For a particularly interesting case, try a foreground color of black
> (#000) against a background of 50% gray (#808080). Sticking with black
> actually has a larger contrast than switching to white!)
>
> It's definitely possible to make this work, but there are some
> tradeoffs that I didn't want to think about at the time, so I went
> with the simpler version currently in the spec.
>
> ~TJ

Yeah, that does make it quite a bit more complicated. I tried to play
around with shifting the hue first, but the hue changes luminosity
enough to ruin the contrast if done after, and to still runs into the
non-monotonic problem you describe if hue shifted before.

I've been working on getting contrast() from the current proposal to
work in cssnext, hoping to get similar functionality to an
ensure-contrast($fgColor, $bgColor) that my colleagues use in sass. I
think contrast() still really valuable as is, and if the goal is to
get maximum contrast, the hue of the foreground color will disappear
anyway.

I'll spend some more time playing with ideas and see if I can find
something more concrete that makes sense.

-Andy

Received on Tuesday, 10 March 2015 03:18:11 UTC