It’s not “spec,” but WebKit browsers support image masks. If you are familiar with Photoshop, they work like that. You declare an image to use as as mask. The black parts of that image hide what it is over, white parts of that image show what is underneath, gray is partially transparent. So if you had this image:
<img src="orig.jpg" alt="trees" class="circle-mask">
And you had this image you created as a mask:
You’d apply it to the image in CSS like:
.circle-mask {
-webkit-mask-box-image: url(mask.png);
}
And this would be the result:
You Don’t Need Actual Images
The first trick we’re going to utilize here is that the image we delcare for the -webkit-mask-box-image
doesn’t need to be an actual graphic image. Instead we can use –webkit-gradient
to create that image. Yes, we could just make an image that is a gradient as well, but creating the gradient mask programmatically means that it’s far easier to adjust on the fly and requires one less HTTP request.
-webkit-mask-position: 0 0;
-webkit-mask-size: 200px 200px;
-webkit-mask-image: -webkit-gradient(linear, left top, right bottom,
color-stop(0.00, rgba(0,0,0,1)),
color-stop(0.45, rgba(0,0,0,1)),
color-stop(0.50, rgba(0,0,0,0)),
color-stop(0.55, rgba(0,0,0,0)),
color-stop(1.00, rgba(0,0,0,0)));
In the above CSS, we’ve created a 200px by 200px image which fades from fully opaque in the top left and fading and about half-way point at a 45deg angle, fades to fully transparent. That would look a little something like this:
Moving The Mask
Notice we set the position of the mask with –webkit-mask-position
. Because we can set the position, we can move the position. We could move it on a :hover
–
.circle-mask {
-webkit-mask-position: 0 0;
}
.circle-mask:hover {
-webkit-mask-position: -300px -300px;
}
Or we could use a -webkit-animation
to automatically move that mask.
@-webkit-keyframes wipe {
0% {
-webkit-mask-position: 0 0;
}
100% {
-webkit-mask-position: -300px -300px;
}
}
.circle-mask {
-webkit-animation: wipe 6s infinite;
-webkit-animation-delay: 3s;
-webkit-animation-direction: alternate;
}
Creating The Wipe
I’m sure all you smarties have already put all this together. The idea is that we have one image on top of another image. The image on top gets the mask, and then we move the mask as needed.
<div id="banner">
<div><img src="images/banner-1.jpg" alt="Skyline 1"></div>
<div><img src="images/banner-2.jpg" alt="Skyline 2"></div>
</div>
#banner {
width: 800px; /* Size of images, will collapse without */
height: 300px;
position: relative; /* For abs. positioning inside */
border: 8px solid #eee;
-webkit-box-shadow: 1px 1px 3px rgba(0,0,0,0.75);
}
#banner div {
position: absolute; /* Top and left zero are implied */
}
/* Second one is on top */
#banner div:nth-child(2) {
-webkit-animation: wipe 6s infinite;
-webkit-animation-delay: 3s;
-webkit-animation-direction: alternate;
-webkit-mask-size: 2000px 2000px;
-webkit-mask-image: -webkit-gradient(linear, left top, right bottom,
color-stop(0.00, rgba(0,0,0,1)),
color-stop(0.45, rgba(0,0,0,1)),
color-stop(0.50, rgba(0,0,0,0)),
color-stop(0.55, rgba(0,0,0,0)),
color-stop(1.00, rgba(0,0,0,0)));
}
Demo and Download
In the download, there is another example where the wipe goes horizontally instead of at an angle, and happens using -webkit-transition rather than animation on a hover event.
More Than Two?
I spent more time than I probably should have trying to see if I could get the animation to wipe three images in succession. It’s kind of possible but I wasn’t able to get it smooth and consistent as I would have liked, so I scrapped it. I’m still fairly sure it’s possible, probably using two different animations with different delays or the like. If you try it and get it worked, do show!
More
Check out the announcement from 2008 for more information about the masks themselves. There are useful bits to know in there, like the mask images can stretch (like full page backgrounds) and repeat. It actually works a lot like border-image, with the nine-box system for stretching/repeating.
Credit
I stole this idea from Doug Neiner who showed me a little demo of the idea. Posted with permission.
Oh wow that’s crazy!! I never knew the WebKit browser could do masks! How do people find out about these things!
Great post :D
genial !!! muchas gracias.
Cool. Shame masks aren’t part of the main spec, though.
Awesome!!!!
Thanks Chris, one more time you open our minds to new horizons.
The web works in mysterious ways!! I was just trying to figure out how to create some kind of “opacity layers” for a site that I’m working on, and this looks like it points the way towards my solution. I take it, this is only possible with webkit and not mozilla or IE. GREAT post!!
Very cool, Chris!
And then, it would be super simple to provide a fallback for non-Webkit browsers — especially with only a two photo transition. Something like….
And then, in the CSS:
Ah yeah, nice!
I’ll update the demo code when I get a chance. I really should offer better fallback stuff like this when I can. Thanks for taking the time to write it up.
Jeff, where and how do I insert the code for the upper half (that begins with “var div…”)? I’m not familiar with that style of coding.
Very COOL!!!!
But why only in webkit again :(
Because masking is a WebKit-only feature.
Superb Chris. Nice idea. But it not practical in real projects :(
Why not? See the fallback above, that’s totally acceptable in “real” projects. Especially since JavaScript can’t really replicate masking like this, it’s a unique effect.
These “it’s not practical” comments always drive me crazy. :)
As long as you can provide a suitable fallback for older browsers, it’s 100% practical. It’s funny how we’re fine with unique viewing experiences for mobile users, or iPad users…but not for old IE users.
In this case, the result is the same in all browsers: you see the next photo. This method simply adds some frosting to the transition. How is that not practical??
This article is great and WebKit masking is very cool.
I have to agree with Chris & Jeffrey this is no reason at all why this is not practical, just make sure there is a fallback and it gracefully degrades for browsers that don’t support it.
I mostly disagree with comments which state that using a piece of code is not practical, especially ‘because it doesn’t work with IE6’.
But keep in mind that maybe he’s just trying to say it’s not practical because there aren’t that many users of Webkit browsers. So a fallback isn’t in this case a ‘real’ fallback (as it should be) because the majority uses a non-Webkit browser. I don’t think that it’s correct to let it degrade in other browsers in this specific case.
However, it’s nice to learn tricks like this one.
It isn’t that “it doesn’t work in IE6, therefore we can’t use it, phhhttf” but it doesn’t work in ANY browser besides Chrome, Safari, and whatever other little >1% browsers out there using Webkit to drive their engines. It’s not practical in the sense that most of your users won’t see the effect. However, as others have noted, if you’re okay with that (i.e. the masking effect isn’t critical to your design or information architecture — and why would it be?), then it’s a tasty little tidbit for your Webkit users. Everyone else remains at status quo without losing anything.
And, if these effects become popular, you can bet the folks at Firefox and Opera will incorporate them into future releases. Maybe even the stubborn bastards at Microsoft…?
This is a particularly important point. Specs are reactions to real world usage and browser vendors also actually integrate the specs based on popular usage.
The problem is I am in India and here most of the users use IE6 so its not practical for me. I try to convince my friends and family to use modern browsers and most of them wont listen to it. Thats the problem.
I love the way that the WebKit project really pushes the envelope of the CSS spec, and I hope masks are taken up by the other vendors.
Imagine if they also added in something like a ‘blending-mode: multiply;’ property, then pretty much the whole functionality of the Photoshop layers palette could be recreated (and manipulated) programmatically!
That’s an awesome thought. :)
I don’t really see the point of stuff like this if it’s not in the spec and only works on webkit browsers. Doing fancy things just for the sake of doing fancy things doesn’t appeal to me, and I find it to be gratuitous.
Of course fancy for the sake of fancy is useless. But you can’t possibly know if the implementation and usage of this is fancy for the sake of fancy. Perhaps this could be used for an iPad specific site for a two-city bike ride, and the header wipes from an image of one city to the image of the other city. It’s guaranteed to work and it’s neat and appropriate for the design.
I was surprised to find your examples work flawlessly on the default Android browser on a HTC desire. I hadn’t realised things like that had been implemented on mobile browsers already.
Just awesome!!! Where do you find this stuff? Then again if you told me that there wouldn’t be a need for a blog would there.
awsome man! as usual!!
I have noticed a lot of comments saying the WebKit browsers have very small user percentages. I think a lot of people are forgetting that webkit browsers also ship on iPad, iPod Touch and iPhone, the default web browser on Android phones is also Webkit.
These then means there are a lot of webkit users out there and this technique is prefect for use on mobile websites or iPad specific versions of a website.
thanks Chris,
I don’t get it. You have rectangle/square shapes, when you could have used borders to pull that trick off.
Where is an example with the circle??
wow chris :O this is totally cool !!!
how bout something firefox has & webkit doesnt have yet?
so people can have different experience when browsing :D
just a thought
thanks chris for the awesome post
Ah Chris, such a good effect. Every time you post a new technique you have discovered I want to go off and build a site demonstrating that exact feature and putting it to full fledged practice.
Annoying part is it can’t happen all that fast with all the time involved supporting those older crappy browsers, integrating back end solution then remembering to show people.
It’s tough being a follower of css-tricks.com you just provide so much inspiration.
Thanks as ever!
Totally amazing Chris. Thanks for always pushing the envelope. I didn’t even know about the mask feature. If other browsers catch up with webkit it’ll bring out the George Lucas in all of us!
Very nice, Its a shame every internet user does not use chrome :)
I think the same effect can be achieved in Gecko using SVG effects on HTML content (which I believe is much more robust way). More info here: http://weblogs.mozillazine.org/roc/archives/2008/06/applying_svg_ef.html
Well considering that safari and chrome are both webkit browsers, and both android and iphone come with webkit browsers this seems like an excellent use for mobile sites. Does this effect work on both the android and iphone default browsers?
I personally believe mobiles sites are going to become just as important as the main site, especially if the site has anything where the user could benefit by accessing while on the road(news, entertainment, social interaction ect.)
Hi Chris, not sure if you’re aware or not, but your body text (myriad pro) doesn’t render so hot on PC/Vista. See http://i.imgur.com/F7NZc.jpg for a screenshot.
anyone using IE6 doesn’t give a sh*t about their web experience so why do people care that this does or doesnt work in that browser? Things like this are great. Shows that people are creative and are advancing in their thinking. Whether or not its supported across the board is not the thing here. And its a treatment that wouldn’t be used all over the place on a site. Its a nice detail to add. It’s all in the details.
Awesome! Now heres a question… any way to do a similar effect but on hover a color image gets its color sucked out of it and turns to black and white, but only using 1 image (no sprites)
That’s cool :)
Much resources here for a newbie like me.
Thanks Chris
its not working on mozila
After (re)reading this article, the great fallback of Jeffrey Way (great teacher, thanks!), and the comments regarding this “wouldn’t be pratical because is only for webkit” in 2010, it came to my mind to see the browser share from 2010 and compare it to today’s behaviour.
In 2010, webkit-based browsers (both Safari and Chrome) averaged at under 13% usage. In 2013, they average at 58%.
For me, this means that those who used extra features (while covered with a fallback) cashed in big time! It’s not just theory – fallbacks (still) are a must.
Hi Muhammed,
The IE6 almost dead. See this link and find the users from India. :D