UI colours

Colour-related issues are abundant in user interfaces: texts are frequently illegible due to low contrast, background lightness can't reliably match user's environment, customisations break colour codes, there's little consistency, colours seem to often be optimised for a pretty picture rather than a usable interface. While some of those issues can't be solved easily, others can, but frequently get ignored. Here is a compilation of my older notes on the topic.

Basic legibility

For a text to be legible, there must be sufficient contrast between lightness of its perceived background and foreground colours. Web Content Accessibility Guidelines describe a contrast ratio ensurance procedure, which works well.

WebAIM's contrast checker allows to quickly check those contrasts online, and so does another contrast checker. NASA recommends similar approaches for colour graphics and legibility in particular.

Background lightness

People work in differently lit environments, the eyes adjust to those. Computer screens commonly emit light rather than reflect it, and using a light background colour leads to effect similar to staring at a lamp when one is in a dark environment (though probably larger e-ink screens will appear sooner than default and common themes will change, and then it will be fine). Often it's the default, especially for web browsers (probably mimicking paper documents, but those don't emit light). Yet in a well-lit environment dark-on-light themes tend to look better.

Usually colour themes can't depend on environment, but in some cases they can depend on user preferences: for instance, Emacs lets packages to provide custom faces (including colours) dependent on whether dark-on-light or light-on-dark colour theme is currently in use (among other parameters). When such functionality isn't available, usually it's still possible to not change colours at all, hence not harming legibility, keeping colours consistent and standard (as used for GUIs), or pick those from a fixed set (as used for TUIs). Unfortunately most common web browsers and other document viewers and editors would use black-on-white themes by default, which are often too bright even for a well-lit environment, and their standard interfaces are generally considered ugly. Apparently there's no good solution, I'm just defaulting to a light-on-dark theme (as seemingly least harmful), with an alternate stylesheet for a non-blinding dark-on-light theme. A green background allows to pick a slightly darker colour while keeping a good perceived contrast with dark foreground text.

Though as of the end of 2019, major web browsers are finally starting to incorporate a mechanism similar to that in Emacs, to respect user preferences, using the prefers-color-scheme CSS media feature, and by 2021 it's available in their stable versions. Though as expected, websites keep messing it up: for instance, when they have okay colours for a dark-on-light theme, they add that property to adjust the background and default colour for a light-on-dark theme, but don't adjust other colours, and then texts where those are used become illegible. And you have to use colour overriding once again, but this time to fix the messed up dark theme. Additionally, if a dark system GUI theme is used, apparently Firefox assumes that dark theme is preferred, and then websites are less comfortable to browse when it's light around, so now one needs both dark and light custom CSS for global colour overrides. On websites like github.com, where users can embed images with transparent colours, it also made some of those illegible (which would be okay if it was a web browser abandoning the silly business with colours and breaking a few websites, but now they are broken while it's still not fixed globally).

I've noticed that for me dark-on-light themes are preferable (and don't feel quite like staring at a lamp) just for a few early hours on sunny summer mornings, even at the minimal screen brightness.

18% to 35% of people may also sneeze when switching from a dark theme to a light one (e.g., browsing the Web while allowing all the websites to set their colours), due to the photic sneeze reflex.


Colours are useful to reflect semantics. Unfortunately they are frequently used to hide semantics instead, by either relying only on colours to carry the semantics where they can change, or even making normally differently coloured elements to look the same (e.g., hyperlinks and plain texts on websites).

Sometimes a few standard colours are available and can be reused for semantic colouring (again, as it is with Emacs faces). They aren't always sufficient, but even additional ones can be distributed as a shared package for use by different applications.

Colour adjustments

Many documents are still composed with poorly chosen colours. A custom CSS (such as Midnight Surfing) helps to deal with HTML documents, and some document/PDF viewers provide colour overriding functionality. Generally it's better than reading original documents, but potentially important colour-coded information can get lost. Some systems and devices try to adjust brightness to match the environment (or just to avoid extremes), but that leads to loss of contrast and worse legibility.

The HCL colour space is handy for such colour adjustments: hue can be preserved to keep matching colours, while lightness simplifies both contrast checking and overall lightness tweaking. One of the HCL/HSV disadvantages Wikipedia mentions is lack of sophistication and unnecessary optimisation for computing speed, but they seem to be more appropriate for legibility measurements than CIELAB/CIE 1931 XYZ, and there are perceivable lags on modern hardware when web browser extensions attempting to use similar approaches are active (in addition to the lags that are always there, that is). Another interesting colour space is HSLuv, which is supposed to be perceptually uniform, so possibly a nicer version of HSL.

Random colour generation

Random foreground text colours are needed sometimes (e.g., for nickname colourisation in IRC clients), and they should have sufficient contrast ratio with the background. An approach I used to generate those is based on the contrast ratio ensurance procedure, generating suitable colours only. An illustration in Scheme is available in random-colour.scm; Elisp versions of that are (or at least were in 2014) available in Circe and rcirc-color. A somewhat simpler approach is just to filter a list of colours using the original procedure.

IWantHue and How To Avoid Equidistant HSV Colors provide more information on the topic, though rather focusing on random colours for diagrams.

Similar approaches are usable to generate whole themes out of reference colours or basic parameters. The LAB colour space is more suitable if colour difference is more important than hue preservation. An Elisp example is available in generated-colour-theme.el.

Colour codes

While generally it's best to avoid, colours can be useful on various diagrams. It would often become invisible/unusable on monochrome displays (e.g., e-ink displays, out of modern ones) or in document viewers with colour overriding, but a nice solution here is to use not just different colours, but also different styles: solid/dashed/dotted lines, different filling styles for areas.

User settings

As mentioned above, common infrastructures make it hard to respect user settings, and apparently in most cases users would even prefer their defaults to be ignored. It's even worse when UIs make assumptions about user defaults, such as setting background or foreground colour, and not setting the other one, or use graphics (for diagrams, mathematical formulae, etc) with transparent backgrounds and fixed foregrounds (while there is currentColor for use with SVG).

Universal design

The previous sections are focused on making colour themes less painful to work with for people with relatively good vision, who can see those colours at all. But the coloured interfaces should also be usable by colour-blind users, and interfaces in general – by blind ones.


While the overall situation—particularly on the web—is rather bad, and there's no good way to solve it on per-website/application or per-user basis, it's still possible to do much better than average, even by checking the contrast alone or not defining colours at all.