Sorting out a color palette

I used a palette generator to come up with the color palettes for this website (there’s a dark mode and a light mode, toggleable via the 🌞:new_moon_face: in the header), but it has a few shortfalls.

Mainly, I’m not super happy with the level of contrast in dark mode, and also when I want to put a game together I need a much higher range of colors to indicate various things. Palette generators love to give you a main color and an accent color; the field of palette generators seems to have decided that five colors is the right amount of colors for a palette. But I want a whole selection of roygbiv’s that all go together.

So, that’s this weekend’s experiment: to make a color palette generator that gives me a good range of hues and contrasts but still looks generally pretty nice together.

Attempt 1

My first thought was to do some physical simulation, placing some color values at some starting point and then applying forces to them so they push away from each other, adjusting hue and brightness until there was a nice palette.

Ended up looking something like this before I decided it was way too much effort for something that I wasn’t sure would actually produce a nice result.

Executing palette.mjs

Attempt 2

I decided to go for something a lot dumber. I took an existing palette (grabbed from Dwarf Fortress) and wrote a thing that generated a light + dark version of each color using a library called ChromaJS, then displayed how they looked against the palette’s black and white values, as well as how the light and dark values looked against each other.

I also got it calculating the WCAG contrast ratio. The goal for readable text is to have a contrast ratio at at least 4.5. I’m not planning to use colored text for anything other than links and headings (ie no paragraphs of color) so I’m happy for the colors to skirt pretty close to that boundary as long as white-on-black pops off.

ChromaJS turns out to be pretty neat. The final method:

  1. generate an initial palette
  2. brighten and darken things to get good contrast values
  3. tint everything with the same color so the palette has a bit of coherence
  4. generated “subdued” (lower contrast + desaturated) versions of the colors to use for visited links, disabled buttons, footer content etc
  5. adjust things in LAB color space to get the lightnesses + chromas a bit more uniform
  6. manually tweak the initial palette until the contrasts are all at >5

The results look like this:

Executing adjuster.mjs