Luke Evers

CSS Text Masking

Posted on 17 October 2014

I've recently come into a problem with CSS Text Masking. After doing some basic research I found that webkit browsers support background-clip: text even though there is not an offical spec for it. The lack of an official spec is the reason that FireFox has yet to implement it.

Implementing this with background-clip: text is extremely easy, but then we don't have full browser support. Let's see what it looks like on both FireFox and Chrome.

All we're going to do is use an h1 for our text masking, and we're going to give it the class .masking in case we ever want to use an h1 tag somewhere else without the text masking.

<h1 class="masking">CSS Text Masking</h1>  

And here's the CSS. I'm assuming that mask.jpg is in the same directory as the CSS file.

h1.masking {  
    background-image: url(mask.jpg);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

Now here's what it looks like on Chrome:

Chrome-Working

And here's what it looks like on FireFox:

FireFox-Not-Working

It looks great on Chrome! Although Chrome has the highest current usage of web browsers, a lot of people--including myself--use FireFox. After doing some research I found that the best way to implement this for FireFox is to use SVG.

We also need to separate our Webkit HTML with our FireFox HTML, so I'm wrapping each in a div with a class related to them.

<!-- START WEBKIT -->  
<div class="webkit">  
    <h1 class="masking">CSS Text Masking</h1>
</div>  
<!-- END WEBKIT -->

<!-- START FIREFOX -->  
<div class="ff">  
    <style>
        .svg-clipped {
            clip-path: url(#svgPath);
        }
    </style>
    <img class="svg-clipped" src="mask.jpg" height="100px" width="auto">
    <svg height="0" width="0">
        <defs>
            <clipPath id="svgPath">
                <text x="0" y="50">CSS Text Masking</text>
            </clipPath>
        </defs>
    </svg>
</div>  
<!-- END FIREFOX -->  

There are two things that need to be set.

  1. In our img tag we set the height="100px", but that number should be determined by what font size we are using.
  2. In our text tag we set y="50", but that number should also be determined by how much text is cut off, and the height of the image we previously set. Play around with the numbers to get it perfect.

Don't forget to use the same font styles in your CSS file on text that you're using on h1 so they match!

In our CSS, by default we set .webkit to display and .ff to be hidden. If someone is using FireFox, the CSS in @-moz-document url-prefix() will take precedence and set .webkit to hidden and .ff to display.

.webkit {
    display: block;
}

.ff {
    display: none;
}

@-moz-document url-prefix() {
    .webkit {
        display: none;
    }

    .ff {
        display: block;
    }
}

At this point, we've got it working in both FireFox and Webkit browsers! I didn't go over IE support in this post, but that is also something else you need to consider when using CSS Text Masking with the current browser support.

You can view the source on GitHub here, and you can view a demo here.

Image

The background image I used for the text masking can be downloaded from here.

KSP

comments powered by Disqus