Making a useless but fun colour randomiser

·

2 min read

Making a useless but fun colour randomiser

There are a couple of different ways of representing colours in CSS. To make a colour random, one of the best ways of going about it is to use the RGB format, which can accept three integer values for red, green, and blue (as well as an alpha value).

A function to produce this is easy enough in TypeScript -

// get a random value between 0 and 255 to the nearest integer
const randomColourComponent = () => Math.floor(Math.random() * 255);

// generate a random colour in the RBG format
export const randomColour = () => {
  let red = randomColourComponent();
  let green = randomColourComponent();
  let blue = randomColourComponent();

  return `rgb(${red},${green},${blue})`;
};

Adding bounds for text legibility

But what if we want to be able to have a random background colour with readable text on top of it? If our text colour is black, then we want to ensure that our random background has a minimum threshold that keeps it from being too dark. Or vice versa.

Such a change is simple enough and only affects the randomColourComponent arrow function.

const VARIANCE = 75; // totally arbitrary
const MINIMA = 255 - VARIANCE;

// get a random value between MINIMA and 255 to the nearest integer
const randomColourComponent = () => Math.floor(Math.random() * VARIANCE) + MINIMA;

You now have a random colour in a bounded range.

Seeded for consistency

But let's take it even further. Suppose we want the colour to be somewhat random but tied to the value of the text that it is for. Maybe we have some tags on the front end that we want colour coded, and these colours should be consistent with the wording of that tag. If this is the case, we can use a seed value to generate our colours. Math.random() is not possible to seed, so we will be using another implementation to this end.

This is accomplished using a hacky parseInt() solution by setting a really high radix. We repeat the seed a couple of times to ensure we get a nice long string to then parse into a jumbled integer, which is not particularly random but I think it gives a pretty good result for this regardless.

const VARIANCE = 75; // totally arbitrary
const MINIMA = 255 - VARIANCE;

// get a seeded, kind-of-random value
// between MINIMA and 255 to the nearest integer
const randomColourComponent = (seed: string) =>
  (parseInt(seed.repeat(10), 36) % VARIANCE) + MINIMA;

// generate a kind-of-random colour from a seed
export const randomColour = (seed: string) => {
  let red = randomColourComponent(seed);
  let green = randomColourComponent(seed);
  let blue = randomColourComponent(seed);

  return `rgb(${red},${green},${blue})`;
};