The concept of a clipping mask is simple: a shape is used to constrain an image, such that the picture is only visible within the confines of the shape, creating a “cookie-cutter” effect.
In past examples I’ve shown how to use various combinations of border-radius, radial-gradient and overflow: hidden to create masks for images, but using text as a mask is somewhat trickier. The Webkit team has a CSS3 proposal to do so, but it’s not yet supported in browsers outside of Safari and Chrome. I wanted a solution that would work cross-browser… even in IE9.
The SVG spec has supported clipping masks for years. Building on what we know of SVG text, it’s pretty easy to integrate a solution.
First, place your image on the page. For all intents and purposes this will be your “background” image, which will show through the clipping mask. I’m using HTML5, so I can just place an image directly in the body:
- <img src="yukon-river.jpg" alt="Knockout" id="knockout-text">
In my case, that image (supplied by Keith Williams under Creative Commons) looks like this:
There are just two conditions for this image: it must be large enough to contain our text, and it must have an id value, which will be referenced in the CSS we will write shortly.
Next, we’ll create our SVG file. This will be a separate document named knockout.svg, with a simple structure:
- <?xml version="1.0" encoding="utf-8" standalone="no"?>
- <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
- "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
- <svg xmlns="http://www.w3.org/2000/svg" version="1.1"
- xmlns:xlink="http://www.w3.org/1999/xlink">
- <defs>
- <mask id="mask">
- <text x="0" y="100" id="knockout" fill="white" style="font-size:120px;
- font-family: Blue Highway, Arial Black, sans-serif;">KNOCKOUT</text>
- </mask>
- </defs>
- <use xlink:href="#knockout"/>
- </svg>
The XML prolog. doctype and <svg> tag are the same between every SVG document, so they are not a big deal. Instead, concentrate on the <text> element: the x and y values are the offset positions for the text, and the fill is the color for the letters. (This must be specified, even though we are showing our image through the letters). The font(s) we wish to use are written in an inline style, exactly as we do in CSS.
The part that is different is the <defs> and <mask> elements around our text. Very simply, this will allow use to specify the fact that we should use the text as a mask (note that the mask has an id). The penultimate line: <use xlink:href="#knockout"/> references the id provided to the text.
Finally, marry the SVG to our HTML content with CSS:
- <style>
- #knockout-text {
- mask: url(knockout.svg#mask);
- -webkit-mask-image: url(knockout.svg);
- }
- </style>
The mask CSS property, used by Firefox, Opera and IE, refers to <mask id="mask"> in the knockout.svg file. Chrome and Safari need the second line, which pick up the mask where it is in specified in the file.
“But,” you might say, “How can I know that what you’re showing here is such an effect? It looks just like a picture!”
Indeed, that’s true: you’ll find that you can’t select the “KNOCKOUT” at the top of this article as text. But if you drag the element to your desktop, you’ll see that it saves as an image: removed from the clipping mask effect, you’ll see the entire landscape. And as I’ll show you shortly, you can edit the text in the SVG document to be anything you want… which is far quicker than going through PhotoShop.