DEV Community

Cover image for How to Determine Font Color based on a Random Background Color
Marian
Marian

Posted on

How to Determine Font Color based on a Random Background Color

Inspired by this great post by @dailydevtips1 about how to create random colors with Vanilla Javascript, I decided to write a little follow-up to make sure, the random color also has a matching font-color.

Creating the Random Background Color

As a reminder, we are generating random hexadecimal number with this function:

Math.floor(Math.random()*10000000).toString(16)

Actually, we might as well use 16777215 as a multiplier, which is the maximum possible decimal for a color (meaning 16777215 === #FFFFFF).

The result of this formula is a 6-digit hexadecimal number. Like RGB colors it consists of three parts:

  • The first two digits represent the color red
  • digits three and four represent the color green
  • the last two digits represent the color blue

Determining the Font Color

To determine, which is the best possible font-color for a certain background, we can follow the recommended algorithm on www.w3.org.

Color brightness is determined by the following formula:
((Red value X 299) + (Green value X 587) + (Blue value X 114)) / 1000

Converting this formula to Javascript could look something like this:

const red = parseInt(color.substring(0,2),16)
const green = parseInt(color.substring(2,4),16)
const blue = parseInt(color.substring(4,6),16)
const brightness = red*0.299 + green*0.587 + blue*0.114
Enter fullscreen mode Exit fullscreen mode

Now we have an integer value for the perceived brightness of our background color.

We took each color from the previously generated random color using substring and converted the hexadecimal to a decimal using parseInt().

Since the variable brightness of our function represents the brightness of our color, we can now use it to define the font color. I found that 180 is a good threshold to switch from white to black, but it's probably best to experiment a bit.

The function to set the font color could look like this.

if (brightness > 180) {
      return { backgroundColor: '#' + color }
    }
    else return {
      backgroundColor: '#' + color,
      color: '#ffffff'
    }
Enter fullscreen mode Exit fullscreen mode

And my whole function looks like this:

  const randomColor = () => {
    let color = Math.floor(Math.random()*16777215).toString(16)

    /* sometimes the returned value does not have 
     * the 6 digits needed, so we do it again until
     * it does 
     */

    while (color.length<6) {
      color = Math.floor(Math.random()*16777215).toString(16)
    }

    let red = parseInt(color.substring(0,2),16)
    let green = parseInt(color.substring(2,4),16)
    let blue = parseInt(color.substring(4,6),16)
    let brightness = red*0.299 + green*0.587 + blue*0.114

    /* if (red*0.299 + green*0.587 + blue*0.114) > 180 
     * use #000000 else use #ffffff 
     */

    if (brightness > 180) {
      return { backgroundColor: '#' + color }
    }
    else return {
      backgroundColor: '#' + color,
      color: '#ffffff'
    }
  }
Enter fullscreen mode Exit fullscreen mode

In an app it would look like this:

Alt Text

Top comments (2)

Collapse
 
devtony101 profile image
Miguel Manjarres

Interesting, could this be used for, say, a website that lets the user dynamically choose the colors? (Primary and accent). Excellent post by the way!

Collapse
 
isarisariver profile image
Marian

I guess so. You just have to make sure that the color the user chooses can be split into red, green and blue. When using random colors I sometimes had 5 digits and the formula did not work, which is why I added the when loop.
Thanks! 😀