home about me

Finding optimal color contrast in Shopify

Expanding on the previous post about automatic high contrast text colors, let’s take a look about how this could practically be implemented in a Shopify theme.

The Problem

The theme offers the possibility to set a custom background color for each product. This is done via a Shopify color metafield on the product level.

This background color will be behind a lot of texts, and, depending on the chosen color, the default dark black text color might offer bad readability. While in this case the background color was imported automatically, using a secondary metafield for the text color would’ve meant a lot of manual work going through possibily hundreds of products.

The Solution

Using the algorithm from the above linked post, it is easy to come up with a way of automatically setting the correct text color from within the Shopify Theme’s liquid code:

Assign the default color, for bright backgrounds:
{% assign product_text_color = 'rgb(0, 0, 0)' %}

Get the background color from the product metafield, and calculate the color components by their visual "weight".
We can use `red`, `green` and `blue` props on the metafield's `value` prop to get a number from 0 to 255:
{% liquid
assign weighted_background_brightness_red = product.metafields.custom.background_color.value.red | times: 0.299
assign weighted_background_brightness_green = product.metafields.custom.background_color.value.green | times: 0.587
assign weighted_background_brightness_blue = product.metafields.custom.background_color.value.blue | times: 0.114
assign weighted_background_brightness = weighted_background_brightness_red | plus: weighted_background_brightness_green | plus: weighted_background_brightness_blue
%}

If the brightness is below the threshold, switch to the bright text color:
{% liquid
if weighted_background_brightness < 128
  assign product_text_color = 'rgb(255, 255, 255)'
endif
%}

Use it:
<style>
:root {
  --color-product-text: {{ product_text_color }};
}
</style>