Your browser now has ample ability to compose image effects on the fly, saving you a trip into an image editor. You can simulate toning effects and deliver the same image in many different ways by combining layered gradients over top of images and blending with the
A need arose while building the Palate Deck website. After I’d placed the banner photos on various pages, I realized I’d need to go back into Photoshop to tint them and town down the contrast so I could overlay other text and images.
Or… did I?
After consulting caniuse for
background-blend-mode support, I realized that a) it’s almost universally supported, and b) if used thoughtfully, it’s an effect that will degrade fairly well when it’s not.
And so I stumbled across a new image compositing trick.
This effect is pretty familiar if you’ve ever digitally tinted a photo: take a photo, then add an adjustment layer over top to tint it, or adjust contrast, or add a gradient.
Unlike an image editor, in this case the adjustment layers are browser-generated gradients. And we’re doing this all with background image properties, and the multiple images they support.
But wait, isn’t this what
filter is supposed to do? I would have thought so too. However, the latest working draft doesn’t have a mechanism for precise image toning. We’re able to control contrast, and rotate the hue through the spectrum (an ability that’s rarely useful in the real world), but it’s unable to apply specific colour toning and subtle differences to various regions of the image.
So this is where we need to turn to layering and blending. To make this work, start by setting up your image as
background-image instead of an
img element. You’ll need to set specific dimensions for your container (and media queries to resize where appropriate) and then use background properties to control it all.
(The above properties are omitted from the following code examples for clarity’s sake, but make sure to re-add them for the proper effect.)
To give you an idea of the adjustment control you have, I’ll walk through the steps to create the comparison blend at the beginning of this article.
To start, I wanted to tint the image. This is easily accomplished by laying a solid-colour “gradient” over top with the same colour at both start and end points, then using the
color blend mode to mix. By adjusting the alpha value of the end points you can control whether the image is fully tinted with the overlaying colour, or whether it allows natural colour to poke through.
The next step was dropping back contrast to let me add text over top. I’m not going to show the text here, but let’s talk about the contrast.
Unlike tinting, we can control brightness and contrast with
filter here. But it’s not ideal since it only applies to the final rendered stack, which means it takes all previous effects with it. In this case I’d like the contrast adjustment to occur on the image before the tint and the red gradient is overlaid, so it won’t work for me.
So we’ll have to fake it with more gradients. I’ve chosen to use two; one a white layer set to 50% opacity and the lighten blend mode, the second a 50% opacity black layer set to darken. Combining those two together lightens the shadows and darkens the highlights. It results in a much greyer image, but that doesn’t matter since I’m applying the tint over top.
The basic image is where I need it now, so the last thing to do is add a red gradient at top of the stack to get the final tone I was shooting for. This last layer has some opaqueness and is blended normally to drop the finished contrast further.
The big caveats for this technique are that support for
background-blend-mode in IE/Edge is non-existent right now, and Safari doesn’t support the necessary
color blend mode yet, so all examples thus far appear broken in those two browsers.
As I said at the beginning, it can degrade well, but you need to plan ahead.
The multiple layers I’m using here are problematic because without blend modes, the rendered result is a muddied mess. It may not always be that bad, but clearly I need to back up a bit with this example.
The compromise I found for this use was pre-toning and contrast-adjusting the photo in my image editor, and then applying the finishing gradients in the browser. I lose out on some of the benefits listed below by doing it this way, but since I know it’s only a matter of time before Safari and Edge are on board, I’m looking forward to adding the full version to the arsenal in the not so distant future.
You could also consider using
@supports to provide a lighter, blend mode free background stack for these browsers, and a second full-featured stack for browsers that do. Support for
@supports intersects nicely, as IE and Opera Mini will simply ignore the block, while Edge and Safari will choose not to parse it. You’ll need to maintain more code, but
@supports does offer a way to avoid pre-toning the image.
So how useful is this, really? Why build up your image toning in-browser instead of simply pre-composing in an image editor?
The answer is flexibility. You may not always be in control of the original image. It might be user-generated or coming in from a CDN. Or you may want to re-purpose it in different sections of your site. Being able to manipulate any source image in the browser is just one more trick for controlling the uncontrollable.
Have comments on this? Tweet at me.