Getting Stylish with CSS Blend Modes ↘

Jacob Vogelbacher
Development

For quite some time, the job of applying blend effects to images used on the web has belonged to Adobe Photoshop. Now with the power of CSS, we can unlock the possibilities of blend modes and create interesting graphic effects without relying on external tools. Similar to Photoshop, blend modes in CSS allow for the colors in foreground and background layers – or elements, in this case – to blend together in a variety of ways.

Since we can use CSS to target multiple elements by class name, a single blend mode could be applied to all the hero images on a site in one fell swoop. We can even use movement and animation to create dynamic color blending effects that would not be achievable otherwise. Not only does this alleviate the burden of manual image manipulation, it creates new opportunities to elevate the visual experience of a user interface.

The properties

The two main properties to be aware of are background-blend-mode and mix-blend-mode. Background-blend-mode defines how an element’s background layers should blend with one another, while mix-blend-mode handles the blending between an element and the elements that are behind it. Using these properties should feel familiar to anyone who has spent time in Photoshop, as they simply take the name of a blend mode – like overlay, multiply, or screen – as their value.

Background-blend-mode

A great way to experiment with blend modes is simply with a color and an image. In this example, the multiply blend mode is used to mix the background-color and background-image of an element.

.bg-color-blend {
  background-color: violet;
  background-image: url(image.jpg);
  background-size: cover;
  background-blend-mode: multiply;
}

With background-blend-mode we can use any combination of background colors, gradients, and/or images. This means we could overlay multiple images on one another with just a single element:

.bg-image-blend {
  background-image: url(image.jpg),
    url(image-2.jpg);
  background-size: cover;
  background-blend-mode: overlay;
}

The background property and blend-mode properties have no limit to the amount of values that can be passed in. So we can mix any number of backgrounds with however many blend modes we like:

.bg--gradient {
  background: linear-gradient(to top, violet, transparent),
    linear-gradient(to bottom, cyan, transparent),
    url(image.jpg);
  background-size: cover;
  background-blend-mode: overlay, soft-light;
}

On its own, background-blend-mode allows for stunning graphic effects to be applied sitewide, and the images can be changed out at any time without ever needing to reference back to a .psd file.

Mix-blend-mode

Now let’s start blending elements with each other. In this example, we overlay a heading element onto its backdrop.

.bg {
  background-image: url(image.jpg);
}

.blended {
  mix-blend-mode: overlay;
}

What makes this property so powerful is the fact that we are not limited to a static effect that could easily be achieved in an image editing tool. Elements can move around the page and blend with one another dynamically.

Here, we use the difference blend mode to ensure that our fixed position menu icon is always visible, regardless of its backdrop. Since the effect of a blend is determined on a pixel-by-pixel basis, we can achieve effects that would not be possible by simply changing the background color of the entire element. As we scroll through the example, the pixels of the menu icon individually change in color to contrast a variety of backgrounds.

One important thing to note when using mix-blend-mode is the stacking context of the elements you wish to effect. In our example above, if the fixed icon had a z-index of 1 and the background image sections were positioned relatively with a z-index of 2, the icon would not appear over those sections since it would be behind them in the stacking context.

Stacking contexts can cause some complications in situations like this where we are blending an element with many others throughout a UI. When an element is not blending with another as desired, it is most likely a matter of the position and z-index properties. But what if we want to prevent an element from being blended without having to make adjustments to the stacking context? This is where the isolation property comes into play. As its name suggests, this property allows us to isolate an element – and its children – from the existing stacking context by creating a new stacking context.

.container {
  background-color: white;
}

.blended-image {
  mix-blend-mode: screen;
}

.content {
  isolation: isolate;
}

In the above example, an image element is being blended with its sibling text elements. This results in an interesting effect on the heading text, and we are able to maintain the readability of the paragraphs thanks to the isolation property. Bear in mind that isolation only delivers this effect when no other stacking context properties like z-index are being used. So if we gave the blended image a z-index of 1, the only way to prevent the paragraphs from being blended would be by giving them a higher z-index.

Bring it all together

Many of the effects we’ve seen so far are interesting in their own rather simple contexts, but how far we can push blend modes in a single implementation to achieve complex effects we would typically only expect to be produced by design tools?

Let’s break this down piece by piece. There is a full height container with a pseudo element that covers the entire viewport. The pseudo element has a white background and a z-index of 1. We’ll refer to it as the overlay.

/* overlay */
.container::before {
  background-color: white;
  z-index: 1;
}

Inside the container are three images of animals. They are given absolute positioning within the container and have a z-index of 2.

/* animals */
img {
  position: absolute;
  z-index: 2;
}

Along with the animals, we have a div taking up the full size of the viewport. It has a background-blend-mode applied to its background image and gradient, a mix-blend-mode of screen, and a z-index of 3. We’ll refer to it as the backdrop.

.backdrop {
  background: linear-gradient(...),
    url(image.jpg);
  background-size: cover;
  background-blend-mode: overlay, soft-light;
  mix-blend-mode: screen;
  z-index: 3;
}

Finally, there is a heading with a mix-blend-mode of multiply and a z-index of 4. Within the heading are some spans, each containing a single letter. These spans apply colors to the letters inside the heading and have a mix-blend-mode of difference.

h1 {
  mix-blend-mode: multiply;
  z-index: 4;
}

h1 span {
  mix-blend-mode: difference;
}

So how are all these things combining to form this effect? The overlay obscures much of the backdrop since elements with the screen blend mode appear white when they are above white backgrounds. We are still able to see the backdrop within the animals because the animals are higher in the stacking context than the overlay, but still low enough in the stacking context to be affected by the backdrop’s blend mode.

The heading, on the other hand, is unaffected since it is higher in the stacking context than the backdrop. However, we are still able to blend the heading with the colors behind it by giving it a mix-blend-mode of multiply. The blending between the letters themselves is achieved by the difference blend mode on the individual spans and a negative letter spacing on the heading.

So stylish

As we’ve seen, blend modes can create eye-catching as well as practical effects both in simple implementations and complex combinations. Even though the CSS properties may not be supported in browsers such as Edge or IE11, we can still put these into use as progressive enhancements that add just a little more zing to our UIs.