CSS3 Text Effects with Webkit Masking

2 minute read

01 Nov 2010

Dead easy but cute little technique this one. I'm working with a design that had an overlay effect over some of the text based headings.

The way I've seen it done before (and I have in fact done it myself) is to simply stick a PNG with alpha transparency on top of the text in question. Granted, this technique does work but it felt like a bit of a cludge. It also means you can't highlight the text underneath it. Annoying and bad for usability.

I then cast my mind back to the stunning Kaleidoscope App website. Using a Webkit browser, look closely at the colour wheel triangle thingy and you'll notice it's spinning. Dig deeper in the CSS and you'll see they're using a really nice masking technique to achieve that.

Simple enough, but I wanted this effect to appear on all browsers rather than just Webkit.

Detecting Webkit Masking Support

Feature detection is the best way to implement this technique. Rather than just seeing if "browser = Chrome or Webkit", you can either use the Modernizr library to do this for you, or simply grab the following line of Javascript and insert it above your CSS.

document.documentElement.className = document.documentElement.style.WebkitMask!==undefined?"masking":"nomasking";

That will add a class of 'masking' to your HTML tag should the feature be supported. And, by including this pre-CSS, you'll get no flickering of content. You can then just add the .masking prefix to styles that use it.

Creating the Mask

Basic Photoshop skills should be enough to create pretty much any type of mask. The key point to remember is that they're unlike Photoshop masks in that they rely on Alpha transparency rather than black or white.

Webkit masks require a PNG with an alpha channel, i.e. a 24 or 32 bit PNG.

Areas of the mask with 0% opacity will hide that section of the element the mask is being applied to. Areas with 100% will render as usual. Then, as you'd expect, you can use anything in-between for partial transparency.

Here's the mask I'm using. I've dropped it in a green container so you can see where the transparency lies.

Sample Webkit Mask with PNG-24


This is the easy bit. For non '.masking' browsers, implement the same 'overlay' technique as you've no doubt done before.

For browsers that do support Webkit Masking, just override the element (for example, an h1 tag) to set it.

.masking h1 { -webkit-mask-image: url(../img/bg/text-effect-mask.png); }

You can then play with the positioning and things should you need to;

  • -webkit-mask-position-y
  • -webkit-mask-position-x
  • -webkit-mask-repeat

Here's a screenshot of the output.

A nice, selectable, accessible, progressively enhanced text overlay effect.

Simple right?

This is a rudimentary use of the Webkit mask. As you can see from the Made by Sofa guys (creators of Kaleidoscope App), you can create some amazing effects and choose either to implement a technique for non-supporting browsers, or just degrade gracefully to a static version, as they've done.

You can also use them on pretty much any DOM element there is, as the comments on the Surfin' Safari docs explain.