Julien Genestoux
Julien Genestoux

Reputation: 32962

JavaScript color contraster

I'm looking for a technique where we could programmatically pick the best color contrast to apply on text over HTML elements of different (unpredictable) background colors.

Since the HTML elements will have different colors, we're looking for a technique that will be able to determine what is the color of the content behind the text, and then adapt the text's color to use the one with the best contrast.

I'm quite sure this can't be CSS only, I've looked for Jquery solutions but couldn't find any... anyone has a clue?

[UPDATE] : Based on the first replies, I guess I need to rephrase. Imagine that I'm building a image sharing service and I want to allow people to tag on the pictures themselves. The pictures can be of any color. How can I pick up the right color of the tags, for each different picture?

Upvotes: 13

Views: 14312

Answers (6)

phucbm
phucbm

Reputation: 893

Here's another approach I got from GitHub where they apply on the color of issue's labels. It actually relies on CSS custom properties with some calculations.

.hx_IssueLabel {
    --label-r:0;
    --label-g:0;
    --label-b:0;

    --lightness-threshold:0.453;
    --perceived-lightness:calc(((var(--label-r) * 0.2126) + (var(--label-g) * 0.7152) + (var(--label-b) * 0.0722)) / 255);
    --lightness-switch:max(0, min(calc((var(--perceived-lightness) - var(--lightness-threshold)) * -1000), 1));

    background:rgb(var(--label-r), var(--label-g), var(--label-b));
    color:hsl(0, 0%, calc(var(--lightness-switch) * 100%));
}

You will need to set the RGB channel separately in custom properties for the background color, then the text color will run from black to white by changing the lightness channel in HSL color. The lightness is calculated by an algorithm that receives RGB as inputs.

Upvotes: 0

J.D.
J.D.

Reputation: 1843

There is now a property called mix-blend-mode in CSS (currently just in draft) that can be used to achieve something similar to what you want.

.contrasting-text {
    mix-blend-mode: difference;
}

CodePen someone has put together demonstrating this: https://codepen.io/thebabydino/pen/JNWqLL

Upvotes: 2

Alex Marchant
Alex Marchant

Reputation: 2510

I think this might save any future researchers a little time, this works perfectly for me. Plug in the red green and blue values into the function and it outputs "dark-text" or "light-text".

var darkOrLight = function(red, green, blue) {
  var brightness;
  brightness = (red * 299) + (green * 587) + (blue * 114);
  brightness = brightness / 255000;

  // values range from 0 to 1
  // anything greater than 0.5 should be bright enough for dark text
  if (brightness >= 0.5) {
    return "dark-text";
  } else {
    return "light-text";
  }
}

Using some code from http://particletree.com/notebook/calculating-color-contrast-for-legible-text/ from @David's answer.

Upvotes: 14

Marco
Marco

Reputation: 29

In just one line this solves the problem:

function getContrast50($hexcolor)
{ 
  return (hexdec($hexcolor) > 0xffffff/2) ? 'white':'black'; 
}

If the contrast need to be reversed just swicth white with black and it does the trick. In php.

Upvotes: -1

SavoryBytes
SavoryBytes

Reputation: 36236

This is my fav resource to calculate the "readability" (contrast ratio) of two colors.

the W3C suggests a contrast ratio of at least 5:1 exists between text and background behind the text http://www.w3.org/TR/2007/WD-WCAG20-TECHS-20070517/Overview.html#G18

From the page:

The compliance rate shown above is the highest compliance rate met. The WCAG 2.0 level AA and proposed Section 508 refresh compliance level is based on achieving a contrast ratio of 3:1 for text with a size of 18 points (14 points if bolded) or larger or 4.5:1 for text with a size less than 18 points. The WCAG 2.0 level AAA compliance level is meet when a contrast ration of 7:1 is achieved for text less than 18 points and 4.5:1 for text 18 points (14 points if bolded) or larger.

Upvotes: 0

Pete Wilson
Pete Wilson

Reputation: 8694

Take a look at http://www.0to255.com . Just a moment's glance at the gradients the site presents will light you right up. You'll have to puzzle, but only for about 20 seconds. It's a great site for such problems and a terrific source of ideas for programmatic solutions. And there's no math involved: just plug in some bytes for rgb vals and go.

Upvotes: 2

Related Questions