Color Thief is really neat; it can scan an image and tell you a couple of things about it:

We used Color Thief in a recent project to scan multiple images and, for each one:

  1. determine its dominant color
  2. use that dominant color as the background color behind the image
  3. set the image to 50% opaque

…the result being an image that appears to be tinted to its dominant color. Here’s the difference; the first image is before tint and the second one is after:

An image not yet tinted to its dominant color

Original image

An image that has been tinted to its dominant color

Tinted image

That looks nice, doesn’t it? You can see many more of them on the project’s Discover page.

There’s Always a but

…but there was one scenario where the tint effect resulted in a lousy experience: bright images. The design called for a few elements to sit on top of the image—some of which are bright themselves—so we needed to be sure that the image's tint is always dark enough to support the legibility of whatever might be on top of it. Here’s one of the problematic images:

The legibility of the elements on top of this bright image is poor

A bright image that’s been tinted to its dominant color

It’s difficult to see the text and the gold icons, and that’s just not cool. To improve the legibility of these brighter images, we figured we had two options:

For consistency’s sake we decided to go with the second option, then had to figure out how to pull it off—how to programmatically say, You know what? This image is too bright, so rather than tint it to its own dominant color, I’d like to tint it with black.

We ended up utilizing the handy every() method, which tests whether all elements in an array pass a test implemented by a provided function. Since Color Thief gives us the image’s dominant color in an array of red, green, and blue values, we used every() to test whether or not all of them were equal to or greater than a number that we felt meant the image was bright—bright enough to warrant a black tint.

The number we chose is 190, which was the sweet-spot for our needs. If all three values in the array are 190 or above, we add a class of bright-photo to the image’s parent element.

Over in the stylesheet there’s a selector that sets a black background color on any element with a class of bright-photo and, with all of this in place, the result is much more legible; compare the image above with this one:

The legibility of the elements on top of this bright image is much better now

A bright image that’s been tinted with a black background

Here’s the code that handles all of the logic described above; read its comments to see how and when certain things are happening, and don’t hesitate to get in touch with us if you have any comments, questions, etc.

// Any image we want to use Color Thief on is given the class 'color-thief'.
var target_images = $('.color-thief');
var color_thief   = new ColorThief();


// For each image...
$(target_images).each(function() {

  // Use Color Thief to get its dominant color, then change it from an array to
  // a comma-separated string for use later.
  var dominant_color = color_thief.getColor(this);
  var dominant_rgb   = dominant_color[0] + ',' + dominant_color[1] + ',' + dominant_color[2];

  // Make the image semi-transparent, then travel up (2) parents, then set that
  // element's background-color to the red, green, and blue values obtained above.
  $(this).css('opacity', .5).parent().parent().css({'background-color': 'rgb(' + dominant_rgb + ')'})

  // If the dominant color is found to be somewhat bright by using the is_bright
  // function below, travel up (2) parents and add a class of 'bright-photo',
  // with which we make some adjustments over in the CSS.
  if (dominant_color.every(is_bright)) {
    $(this).parent().parent().addClass('bright-photo');
  }

});


// If each value in an array is equal to or above 190, return true.
function is_bright(element, index, array) {
  return element >= 190;
}

Thanks for reading!