61 comments

[ 2.5 ms ] story [ 111 ms ] thread
"Never make the text color of labels grey,"

Honestly surprised GitHub did this.

I've worked with software where a user picks a color for something that renders text atop it. Never once did I think to allow for an in-between color.

The problem is that everyone says this but then nobody defines 'grey'.

It's been a while since I've done UX but I remember a couple of rules of thumb involving projectors (if you work on project management tools it is a certainty that your tool will be used in anger on a projector, and shitty UI in an emotionally charged room is a toxic cocktail).

Anything greater than #eee is indistinguishable from white, and anything less than #222 is indistinguishable from black.

In the days before font weights actually worked, you could do three font weights by mixing #222, #444, and bold.

So that's a third of the greyscale range that isn't grey, at least, and it also misses other mostly-grey colors, and a bunch of shades of blue. Which I think is a long way of saying it's not grey that's the problem, it's low-contrast that's the problem. While grey is heavily represented in that set of colors, it's not all of them, and it might not even be half of them.

That's not the problem here, where they clearly defined the goal colors as 000 and FFF, but the math fails sometimes.
It's fine, they don't use grey, they use gray. /s
I think this is a bug. I'm pretty sure the calculations are meant to flip from black to white in an instant. But the tools provided make that very difficult.
The "almost unreadable" tags near the bottom of this page reminded me of the Visual Contrast Test, which is said to be an indicator of mold issues in the body: https://www.vcstest.com/

For example I couldn't tell the text at all in any of the four tags, including the "hard to read" or "quite unreadable".

> For example I couldn't tell the text at all in any of the four tags, including the "hard to read" or "quite unreadable".

For what it's worth, I couldn't tell the difference either. All of them were completely incomprehensible.

In my current reading conditions (on my phone, outside, nighttime) I couldn't even tell there was any text. They all appeared the same solid grey.
What is a "mold issue"?
From the above website (I'm not advocating that it's right just this is the claim):

> What can cause a contrast sensitivity deficit? > Many things can affect the ability to perceive contrast. These include nutritional deficiencies, the consumption of alcohol, drug/medication use, and exposure to endogenous or exogenous neurotoxins and/or biotoxins, including volatile organic compounds (VOCs), venom from animal or insect stings or bites, some species of mold and the mycotoxins and microbial VOCs they produce, cyanobacteria, dinoflagellates (particularly Pfiesteria and Ciguatera), apicomplexans, parasites, heavy metals like mercury and lead, and the pathogens responsible for Lyme disease and its common co-infections. For more information, see our Research resources.

Wouldn't the results of that online visual contrast test depend on your monitor's color calibration, etc? Or is it designed in some way that avoids that affecting the results? I'd hate to think my body was infested with mold when I'm actually just using a crappy 10-year-old monitor.

Edit: I see from the FAQs there's some kind of display calibration portion at the start of the test; should have read the website more carefully before asking!

I've also found in the dark mode that the background colors of those labels are transparent and I think modified a bit (I'm not sure how to tell) to lower the contrast.

Basically they have this muted pastel look which I know is the stylish thing, but it means there aren't really more then half a dozen distinguishable label colors if that, because the contrast is hindered so much by whatever they've done to it.

I expected to learn more about visual contrast / ux / ergonomics, but he's a topology math guy. Unexpected and delicious.
You can’t make a conditional using < and ?: in CSS, can you? That’s why they are using a very sharp black/white gradient, which unfortunately creates a gray in some cases. Apparently the contrast is not sharp enough.
Yeah I think it doesn’t exist.

In theory a solution would be something like:

  clamp(0,(var(--perceived-lightness) - var(--threshold)) * Infinity, 1)
But most browsers don’t support Infinity. I assume that GitHub can find a suitably large number to put there though. (Maybe I’m wrong though because of precision issues elsewhere).

Another potential solution would be with sign but this function is also largely unsupported

Some browsers have round() and sign(), either of which can make it work. It's a pity that defining sign(x) as x/abs(x) breaks down when x = 0, otherwise you could use that since abs(x) = max(-x,x), and max() is supported widely.
You don't need much to figure out a conditional, for example here you're dealing with two cases before and after 0.453, so just subtract this threshold from a value, divide this number by the absolute value of that number, and now you have -1 for a number before the threshold, and +1 for the number after the threshold. You can normalize it by dividing it by 2 and adding 0.5. Now you have a number `t` that is either 0 for the input before the threshold or 1 for the input after the threshold. You could use it to switch between two values like so: bt + a(1-t)

In the case of generating a white or black number, this works (unless you want a number between 0 and 255, then just multiply the result by 255): https://i.imgur.com/hXNw0EA.png

Dividing by the absolute value fails for 0. Also, only some CSS implementations support abs().
The proposed color-contrast() function in the CSS Color Module Level 6[1] will make solving this problem a lot easier. Rather than doing some messy, complicated calculations on individual color component values, this new function will allow you to pass in a base color, an optional target contrast level, and a list of possible foreground colors (defaulting to white, black). The function will choose the first option that meets the target contrast, or the highest contrast if no target contrast level is supplied.

For example:

  contrast-color(
      wheat tbd-bg wcag2(aa),
      bisque, darkgoldenrod, olive, sienna, darkgreen, maroon
  )
will return "darkgreen".

- "wcag2(aa)" means level AA of the WCAG2.1 luminance contrast algorithm, which computes to "4.5".

- "tbd-bg/tbd-fg" sets whether it is determining the background or the text color.

This proposal is still in the experimental phase, and not all parts of the spec are finalized (such as the tbd-bg or tbd-fg keywords, or even the name of the function itself).

[1]: https://w3c.github.io/csswg-drafts/css-color-6/#colorcontras...

Seems like something that could be calculated and baked server side
For accessibility, it’s better to do this client side, so clients can adjust it themselves to be more contrasting or whatever.
that's cool. use both. calculate a good default contrast server side, use proposal to allow client side to override default
Unless it's a dynamic arbitrary colour (user-selected, overlaid on an image, etc.) then there's not much reason to be doing colour contrast calculations.

Your site's design should just have well-chosen colours.

The only reason this is a problem is because different monitors have different display characteristics compounded by arbitrary viewing environments. A client-side function can measure neither the response of the monitor nor the ambient light of the room, so this problem can never be solved in this manner.
Both of those are already APIs today in phones.

And there's decent reason to not want to tell the server either.

So GP was relevant because that’s exactly what GitHub is doing: dynamically picking arbitrary colors and trying to put appropriately contrasting text on them.
But you still need to pick contrasting colors manually ? This one isn't making new ones for you.

CSS function doing "here is color A, here is color B, make one that is same hue as color B but contrasting" would be much more useful

Clients are free to provide a contrast dial independently of that. For example there’s a Font Contrast extension for Firefox.
If it's a static colour, sure. But if it's set by the user with a colour picker, that doesn't really work.
except the server doesn't know if the client prefers light or dark mode
Great, maybe HN can use it instead of fucking light gray on white
HN uses light grey text in certain applications to intentionally make it harder to read. For text submissions, it's to discourage their use over link submissions. It's a mistake, in my opinion, but it's been like that from the very start.
Part of the reason people come to HN is because it never changes.
This is so silly. Just because radical change is alienating doesn’t mean that smaller improvements wouldn't be positively received. For example, an end to silently swallowing emoji would be an improvement, not a regression. Poor design that actually excludes people is not a treasured feature.
I'll bite: How does swallowing emoji exclude people?
It excludes annoying people who use emojis. I just wish it was updated to include removing the ascii emojis they unnecessarily add, often at the end of posts :)
If a feature excludes a certain kind of people, it might very well be an improvement.
Excluding people that want to shove emoji in is morally good thing.
I treasure not having to look at emojis on HN. Not sure who this "excludes" but I'm fine that that
HN changes all the time. There are lots of new features added that were not present when I first stumbled upon this site.
It’s an unfortunate decision. Makes things like thoughtfully written Launch HNs painful (literally, for me anyway) to read.
There are extensions you can get that will insert stylesheets scoped to specific pages. HackerNews, a site that never changes is a perfect use-case for something like this

I use it for a number of sites I browse regularly

I use Dark Reader to increase the contrast of HN and also make it "dark mode". Highly recommended extension; you can undo a lot of designer-inflicted damage with one click.
Even the top bar is barely legible, light grey on light... whatever color is that.

Or maybe just whoever designed that had different monitor settings than average user and it looks okayish there...

Site note: on mobile it’s easy to get a bit trapped trying to drag and scroll because you end up spinning the 2 diagrams instead
This reminds me of something (perhaps Raymond Chen?) writing about how people think selection coloring is just an easy "invert the colours" and pointed out a midrange selection color would make that inversion not work.

I think I read that while I was at uni, so well over 20 years ago now. GitHub messing this up now seems disappointing (and aren't they part of MS now? shouldn't this be on the standard "new ui QA tasks" list?)

It’s not like MS has had a particular lucky hand in UI over the past 10+ years, and also AFAIK GitHub is still a relatively independent operation.
The terminal emulator I use uses the strategy of swapping the background and foreground colors. This is decent most of the time, but it also has some undesirable corner cases:

1. You can't use selection as a hack to make text more legible. Some terminal emulator always use black on white for selection, which helps in this case.

2. If you select a region with the same background and foreground colors, then the selection itself is invisible.

(comment deleted)
The headline on gh is kind of illegible. It was changed and corrected for here on hn. I am reminded of this sentence: "this sentence no verb".
2023 and axis lock is still an issue in gfx ... sigh
Not to brag, but I wrote an article[1] on HSLuv which is very well suited for this kind of "contrast ensuring color selection".

Some new color spaces with the same purpose exist now, maybe I should update it.

[1]: https://www.kuon.ch/post/2020-03-08-hsluv/

Great read.

> I submitted a bug report to GitHub; hopefully it gets fixed soon!

How do you report bug about GitHub itself?

I tried to do that before (for other issues) but never find the right place.

All the labels in the test repo are perfectly legible for me on Github's Dark theme, this seems to be only a problem with the light.
Linear arithmetic in sRGB strikes again. Although calculating perceived brightness in a linear colorspace is also just an approximation, but it's still significantly better than doing linear arithmetic in sRGB.

Imageworsener has a nice page about this issue in the context of converting to grayscale:

https://entropymine.com/imageworsener/grayscale/

From the OC:

"The value where perceived-lightness equals the lightness-threshold is a plane cutting through the cube ... The intersection between the cube and the plane is a parallelogram..."

Face palm smack.

Of course it is. Feeling really stupid I never realized this before.

Great article.