www.home212.com


Mask


You are using an outdated browser. Please upgrade your browser or activate Google Chrome Frame to improve your experience.

Almost one year ago I wrote an article that dealt with an emerging WebKit CSS technique, the CSS filter effects, and the question if we could not have/emulate them in other browsers, too. Turned out we could.

Today I want to talk about another WebKit-only feature and show you how you might be able to use it across all of the browsers: This is about…

CSS masks were added to the WebKit engine by Apple quite a while ago, namely back in April 2008. Masks offer the ability to control the opacity/transparency of elements on a per-pixel basis, similar to how the alpha/transparency-channel of "24-bit"-PNGs or 32-bit-TIFFs work.

These images consist of the usual R(ed) G(reen) and B(lue) channels that define the colors of each pixel. But on top there is a fourth channel, the alpha channel, that defines every pixels opacity through luminance: White meaning opaque, black meaning transparent, and countless grey values defining the semi-transparent inbetweens. As you can see in the picture to the left.

Masking used for user avatars to style them in a certain shape. Neat! So what could that be good for? Well, masking could be used for images to style them in shapes. Or you could have long scrollable text smoothly fade out by using a mask image with a gradient from opaque to transparent.

As with the background-image property you can also use a CSS gradient instead of an actual bitmap image, as in this code example:

Note: Beware that this is the "old" syntax that will soon be replaced by linear-gradient(to bottom, rgba(0,0,0,1), rgba(0,0,0,0)) (the destination keyword changes to to bottom). Lennart Schoors has a short article on that topic.

The good news: Turns out the other browsers do have different capabilities which we can use as hooks to emulate WebKits proprietary CSS masks. Woot!

So lets say we want to mask an HTML element to the shape of a mouses head as seen in the picture on the right.

And finally we need to have a proper mask image. We cannot simply use the image from WebKits proprietary CSS mask, since SVG masks do not look at transparency values but at luminance values. So what we need to do is turn all opaque image pixels into shades of white.

And KABOOOM! Masking of HTML content is up and running in WebKit, Firefox and Opera! Nice.

We could think about hiding the SVG parts for IEs using conditional comments but Microsoft decided for IE10 that they remove CCs altogether. So no solution yet.

Note 1: The backslashes you see at the end of lines inside our strings allow for multiline strings. They are supported by every browser and were officially standardized with ECMAScript 5.

Note 2: Isnt document.write the Antichrist of JavaScript best practices? Hes nuts! Why is he using it? Well, nothing is just black and white - it all depends on the context. document.write is indeed very very bad if you make use of it in external JavaScript files. document.write forces you to embed external scripts at predefined places of your HTML and prevents almost any attempts of making them load asynchronous. And that means that if these external scripts fail to load, theyll bring your page to a grinding halt. But we are not dealing with an external file here - and you should leave it that way. So there is no blocking. Plus, thanks to having JavaScript outputting the extra markup to the screen while the HTML parser is still running you dont get to witness any flash of unstyled content (FOUC) as it would be the case if you fired a script on DOMContentLoaded. Now back to topic…

We could stop here and all be happy. But how about getting CSS masks working in the IEs, too? Wouldnt that take the cake? Well then, lets go…

Internet Explorers 4 - 9 have a proprietary filter named "Chroma". What the Chroma filter does is comparable to the filmmakers bluebox / greenscreen technique: it lets pixels of an element in a defined color vanish from the screen. The color is therefore used as a "color mask".

The following CSS code would let disappear all cyan colored parts of an element:

Now, whats even more interesting with the chroma filter is the fact that the filter does not only look at the colors of the filtered element itself but also takes into account its children. Because of this one could create some sort of 10px thick frame by applying the following styles:

Then the cyan area of the element .child would be punched out of the filtered element .parent and we could look through it.

So coming back to our mouse shaped example, what we need to do is create a version of the mouse shape image, where the outer parts are cyan and the inner shape is transparent as seen on the right.

Saving with just 2 colors removes the anti-aliasing from the shapes borders. The reason we need to do that is because the chroma filter can only punch out one single color.