Bennett Feely has been doing a good job of showing people the glory of CSS blend modes. There are lots of designerly effects that we’re used to seeing in static designs (thanks to Photoshop) that we don’t see on the web much, with dynamic content. But that will change as CSS blend modes get more support. I’d like to look at the different ways of doing it, since it’s not exactly cut and dry.
CSS Multiple Backgrounds Blend Modes
You can blend background-image
s together, or blend them with background-color. It’s a simple as:
.blended {
background-image: url(face.jpg);
background-color: red;
background-blend-mode: multiply;
}
See the Pen Background Blending by Chris Coyier (@chriscoyier) on CodePen.
Multiply is a nice and useful one, but there is also: screen
, overlay
, darken
, lighten
, color-dodge
, color-burn
, hard-light
, soft-light
, difference
, exclusion
, hue
, saturation
, color
, and luminosity
. And also normal
which reset it.
Adobe (who works on the spec for this stuff) created this Pen for playing with the different possiblities here. Update: they have removed that Pen, but do still have this explainer page.
A single element can have more than one background, stacked up. Like:
.graphic-or-whatever {
background:
url(grid.png),
url(building.jpg)
}
Those can blend too simply by adding a background-blend-mode
.
See the Pen Multiple Background Blending by Chris Coyier (@chriscoyier) on CodePen.
Here’s a cool and practical example by Bennett Feely:
See the Pen rxoAc by Bennett Feely (@bennettfeely) on CodePen.
Here’s another, which cleverly re-combines a color image separated into Cyan / Magenta / Yellow / Black parts (CMYK). You know that’s how offset lithography works in print, right? =)
See the Pen CMY/CMYK Color printing with background-blend-mode by Bennett Feely (@bennettfeely) on CodePen.
Arbitrary HTML Elements Blend Modes
Blending backgrounds together is pretty cool, but personally I’m less excited about that than I am about blending arbitrary HTML elements together. Like a <h1>
title over a background, for example. Or even text over text.
I saw this at an airport the other day and snapped a pic because I thought it looked neat and figured I could figure out how to do it on the web:
My first attempt to recreate it, I used opacity. But opacity really dulls the colors and doesn’t make those overlapping bits have the extra darkness they should have. CJ Gammon showed me there is a blending property precicely for this purpose: mix-blend-mode
.
So to reproduce this:
<h1>hungry?</h1>
Then break it up into s with Lettering.js:
$("h1").lettering();
Then squeeze the letters together with negative letter-spacing, set the mix-blend-mode, and colorize:
h1 {
font-size: 7rem;
font-weight: 700;
letter-spacing: -1.25rem;
}
h1 span {
mix-blend-mode: multiply;
}
h1 span:nth-child(1) {
color: rgba(#AB1795, 0.75);
}
/* etc, on coloring */
Compare:
See the Pen Overlapping Letters by Chris Coyier (@chriscoyier) on CodePen.
Like I mentioned, real web text over image is a pretty sweet use case if you ask me:
See the Pen GxlBm by Chris Coyier (@chriscoyier) on CodePen.
Canvas Blend Modes
The DOM blend mode stuff is most interesting to me, but it should be noted that <canvas>
has blend modes as well and it has a bit deeper support (see below for all that).
You set it on the canvas context. So like:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.globalCompositeOperation = 'multiply';
That value can be any of those I listed above. Here’s a simple demo:
See the Pen canvas blend modes by Chris Coyier (@chriscoyier) on CodePen.
And a fancy one where you can see the blending give the demo life:
See the Pen sketch.js Demo by Justin Windle (@soulwire) on CodePen.
SVG Blend Modes
As you might suspect, SVG does have its own mechanism for doing this. One way to do it is to define it within the <svg>
itself, and it’s fairly complicated:
<svg>
<defs>
<filter id="f1" x="0" y="0" width="1" height="1">
<feImage xlink:href="#p1" result="p1"/>
<feImage xlink:href="#p2" result="p2"/>
<feBlend mode="multiply" in="p1" in2="p2" />
</filter>
<path id="p1" d='M100 100 L200 100 L200 200 L100 200 Z' fill='#00FFFF'/>
<path id="p2" d='M150 150 L250 150 L250 250 L150 250 Z' fill='#CC3300'/>
</defs>
<rect width="100%" height="100%" filter="url(#f1)"/>
</svg>
See the Pen Fnvdp by Chris Coyier (@chriscoyier) on CodePen.
The good news is that mix-blend-mode
will work on inline SVG. So if you’re using SVG that way, you can target the shapes themselves with classes or whatever and give them whatever blend mode you want.
Here’s an example by Bennet that does just that:
See the Pen KDkCj by Bennett Feely (@bennettfeely) on CodePen.
Browser Support
For canvas: Firefox 20+, Chrome 30+, Safari 6.1+, Opera 17+, iOS 7+, Android 4.4+. Worst bad news: No IE.
For HTML/CSS: Firefox 30+, Chrome 35+, Safari 6.1 (apparently not 7?). Not quite as supported as canvas.
At this second, for Chrome, you’ll have to run Canary, go to chrome://flags/ and enable “experimental Web Platform features”.
This actually it a bit more complicated, so if you really want to dig in and know about support, check out the Support Matrix from Adobe.
Progressive Enhancement
What is nice about blending is that the whole point is designerly effects. If they aren’t supported, you can take care to make sure the fallback is still readable (progressive enhancement!).
Here’s a recent thought by Jeremy Keith:
It is entirely possible—nay, desirable—to use features long before they are supported in every browser. That’s how we move the web forward.
So one way to do support is to look at the design in a non-supporting browser and if it is still readable/usable, you’re good, no further action required.
If the result ends up unreadable/unusable, you could tweak things around until they are, or run a test to determine support and do something specific in the case of non-support.
To test for support, I guess you could do test for the property you want to use:
var supportsMixBlendMode = window.getComputedStyle(document.body).mixBlendMode;
var supportsBackgroundBlendMode = window.getComputedStyle(document.body).backgroundBlendMode;
If the returned value is “normal” (or anything other than undefined
) support is there, otherwise not. Then probably apply a class to the <html>
element so you can know that and use it anywhere in your CSS to adjust things, Modernizr style. Perhaps they’ll even do a test for it in the future.
Unless it’s not that simple in which case let me know.
Need more ideas? Check out this collection. Happy blending!
Not sure, but I think the blending modes are what’s crashing mobile Safari o my iPhone 5s. Any one else having the same problem?
Amazeballs. I wonder if Adobe is intentionally trying to make their flagship software obsolete by ultimately being able to code your entire project without the use of an image editor. Hmmm.
They’ve been pretty blatant for a while now about the fact that they’re trying to obsolete Flash, even if they haven’t outright admitted it.. I suspect they see it as competition to some of their newer web design software, and I wouldn’t be surprised if they intend to make something newer and cleaner for game development and the like also.
So you think image editors will be obsolete because you can do the same with a text editor? Well, why use a digital camera then, when you can just code your holiday memories?
I can’t wait to re-read this article once Chrome stable reaches 35. In 33.0.1750.117 the top image is opaque (which is to be expected).
For someone using Canary (or an equivalent Firefox nightly), how’s performance? Depending on how fast or slow it is, it might not be worth switching from prerendered images for this, at least not yet.
That’s weird, I have the same Chrome version on OS X Mavericks and it’s working fine for me.
Covarr, did you enable the experimental features in Chrome? Working fine for me in Chrome 33.0.1750.146 m on Windows 7.
This is pretty cool, I definitely think the text overlay might be the best usage. At least, I’d probably use it the most.
For those of us who are not watching nightly build notes and may be a little behind (I, like most of us, have been working way too many hours lately) on some of the recent support announcements, a quick canIuse type chart would be SUPER helpful for this article. I’ll second what Covarr says… I look forward to reading this article when it actually matches with browser releases.
Your original opacity version would work fine but the colour your using is 20% lighter (if opacity is 80%) so you just need to use a colour thats 20% darker to start with so that you end up with the original hue but at 80%
I am already using this but I can find a few flaws with this, on Internet Explorer 7 (I know don’t ask lol) when I move my mouse over the rollover image, it rolls up then rolls back down again! Is anyone else having this problem? I am also running on 1280px X 968px
IE7 is the least of your worries when it comes to Blend Modes. They don’t (currently) work in the stable version of Chrome, and even in Chrome Canary you have to turn on an experimental mode. I’m guessing IE10 (maybe even 11?) doesn’t even support this…
but when it is full supported it will be amazing!
CSS Blending looks pretty cool. Gonna to try background image and text blending. Thanks for sharing.
Support is very minimal at present, but this means even less usage of Photoshop(which is always welcome).
I always welcome anything that will get me out of relying on Photoshop to create graphics, especially if the site’s content is managed by a client or third-party without an in-house graphic design. Currently I’m using a mix of opacity overlays and grayscale filters to emulate some of the effects.
Next up for Adobe: CSS that emulates Photoshop’s horribly misused chrome filter.
awesome chris
Carl, yes, that’s correct. Atleast here. I’m not so sure but that crash might be something at the level of device settings.
Am so much of a newbie that my first impression on this website is if it was actually built by Human.. Chris, you’re doing wonderful, am only good in buying themes..
However, am having issues with my website, please how can i add border around the blog post and the side bar widgets? just like that of Sahifa themes. My themes is running on Genesis frame work
Thanks for the great tutorial! I read about this and masking on the Smashing Magazine site. They did not include ‘background-‘ and did not see the changes in Chrome. Thanks again!
Woooah, read this post and I love the idea of blend modes, BUT I ran into a fairly major, unexpected problem, and it took me quite awhile to figure it out.
Enabling Chrome’s “experimental Web Platform features” actually caused AdBlock and LastPass to not work correctly – parts of them wouldn’t display. Weird connection, but somehow the problem resolved when I disabled those “experimental Web Platform features” again. Hopefully no one else runs into this issue!
Using Chrome 35, still had to enable experimental Web Platform features to get many of the embedded Pens to render properly. The Adobe one does not render properly at all when embedded, flags on or off, but works correctly when viewed on CodePen itself, which is weird…
That is odd, all of the pens seem to be working fine for me without turning on experimental web platform features. (Chrome 35 on OS X)