CSS Clipping and Masking: Examples and Observations

On Monday I walked through the spec for css clipping and masking. Since the post grew a little long, I promised some examples for today. I’ll also offer a few observations at the end of the post.

The setup for these examples is actually quite simple. The html is little more than a div filled with text for some of the examples and an image for others. The difference you see in the screenshots below is mainly the difference in how the div or image was clipped or what I used to mask it.

As a reminder browser support for both clipping and masking isn’t quite there yet, but it’s not that bad either. More browsers support both clipping and masking than don’t support them. In practice I couldn’t get these examples to work in Safari, though they did work in Webkit Nightly. I’m not sure why, since Safari is supposed to have support. The screenshots below are all from Chrome Canary.

Shapes Reminder

The clipping examples below use basic shapes to clip an element or image so as a quick reminder here’s how those shapes work. If you need more detail about how these work, you can check my post on css shapes.

rectangle)<top>, <left>, <width>, <height>, <rx>, <ry>)
circle(<cx>, <cy>, <r>)
ellipse(<cx>, <cy>, <rx>, <ry>)
polygon(<x1> <y1>, <x2> <y2>, ..., <xn> <yn>)

Clipping Examples

I thought I would start easy and work with clipping before masking. The rather simple html I used is below.

<div class="rectangle">
  <p>< /p>
  <p>< /p>
  <p>< /p>
  <p>< /p>

Each of the paragraphs was filled with some lorem ipsum text and I added some general and arbitrary default styling.

.rectangle {
  margin-top: 10em;
  width: 660px;
  height: 660px;
  background: #696;
  padding: 1em;

Here’s how the above looks without any clipping applied.

Example of div and text before clipping

To play around I just added the -webkit-clip-path property with a variety of values. First I tried circles and ellipses. Below are the results along with the clip-path and value used.

Clipped circle and oval
-webkit-clip-path: circle(50%, 50%, 50%);
-webkit-clip-path: ellipse(50%, 25%, 50%,25%);

For the next few example I reduced the height of the original div to 330px and clipped the original with different polygons.

Clipped polygons
-webkit-clip-path: polygon(0 0, 0 100%, 100% 0);
-webkit-clip-path: polygon(16.67% 50.00%,33.33% 78.87%,66.67% 78.87%,83.33% 50.00%,66.67% 21.13%,33.33% 21.13%);
-webkit-clip-path: polygon(10.42% 67.00%,31.58% 95.62%,90.67% 73.87%,96.33% 39.25%,45.42% 43.13%,17.83% 9.13%);

The triangle I was able to work out for myself easily enough, but I didn’t try to figure out the more complex polygons. Instead I used the polygon tool to visually create them and let the tool give me back the code to use.

Masking Examples

For masking I decided to use an image instead of a simple rectangle. Once the again the html is trivial.

<div class="image">
  <img src="images/strawberry-fields.jpg" alt="Strawberry Fields, Central Park, NY"width="660" height="auto" />

The image is one I took a few years ago in Central Park of the Strawberry Fields memorial for John Lennon. Here’s how it looks without any styling applied

Strawberry Fields Memorial, Central Park, NY

Even though this is the masking example I thought I would first clip the image and I experimented using a circle.

Image clipped with a halfish circle
-webkit-clip-path: circle(50%, 25%, 60%);

You can see that using a circle for the clip-path doesn’t mean you’ll end up with a circle. By varying the x and y offsets and the size of the radius you can create more interesting shapes.

Let’s get to some masking.

First I tried to mask the image with simple linear and radial gradients

Linear and radial gradient masks over an image
-webkit-mask-image: linear-gradient(to right, black 0%, transparent 100%);
-webkit-mask-image: radial-gradient(50% 50%, black 20%, transparent 100%);

After that I decided to have a little more fun and play around with some of the other masking properties

Repeating radial and linear gradients used as masks

The example on the left in the image above uses the css below. Setting the size of the mask to something less than 100% and repeating it led to an interesting effect.

-webkit-mask-image: radial-gradient(50% 50%, black 20%, transparent 100%);
-webkit-mask-position: 50% 50%;
-webkit-mask-size: 50%;
-webkit-mask-repeat: repeat;

Changing the mask size to 10% produced the example in the middle and changing the gradient to linear and the mask size to 20% produced the example on the right. The code for this last example is below.

-webkit-mask-image: linear-gradient(to right, black 0%, transparent 100%);
-webkit-mask-position: 50% 50%;
-webkit-mask-size: 20%;
-webkit-mask-repeat: repeat;

Next I decided to experiment with some image masks. I grabbed a drawing I had done years ago of Starry Night to use as an image mask. I opened the image in Pixelmator, selected a portion of it and applied a gradient. Then I created varying levels of transparency in the entire image to create 3 different masks.

Image masks created from a drawing of Starry Night

The css was simple. It just needed a link to the image mask I wanted to use.

-webkit-mask-image: url("path-to-image-mask.png");

Below are the results of applying each of the above masks to the original Strawberry Fields image.

Result of applying images Starry Night masks to Strawberry Fields image

For my last bit of experimentation I created a couple of images of text and used each as the mask. Again the css was simple as it’s the path to the image mask.

-webkit-mask-image: url("path-to-text-image-mask");

You can see the results below. The only difference between the two is the font used for the text. Don’t ask me which fonts though, since I forgot which I used. The text on the right is actually the same as on the left.

Results of applying two text masks made from images

More Examples

I’m hardly the only person to play around with css clipping and masking so here are a few more examples from others.

These are plenty more examples online if you care to search. These are just a few I happened across while researching this post.

Observations and Closing Thoughts

I didn’t try every combination of every clipping and masking property. I barely scratched the surface of possibilities. Still you can likely see how a little bit of experimentation and creativity can lead to some interesting results.

One thing I didn’t try at all was SVG clipping and masking, mainly due to my own lack of skills working with SVG.

I never could figure out how the source-type properties worked. No matter which value (luminance or alpha) I used, the results always looked exactly the same. I assume the issue was in the masks I applied and that the ones I used wouldn’t show any meaningful difference between luminance and alpha.

It was very easy to get both clipping and masking to work. What took a little more time to understand was how to control them, at least to whatever degree I actually learned to control them.

Like I said at the start I also couldn’t get these examples working in Safari, though they did work in Wekbit Nightly. I’m not sure why as Safari is supposed to support clipping and masking.

Finally in my post about css shapes I mentioned that I wasn’t able to constrain the background behind a shape and that it remained a rectangular box despite my efforts. Alan commented that it could be done using -webkit-clip-path with the same shape as -webkit-shape-outside. Yep. It works perfectly. Thanks Alan.

css shape without and with clipping applied
My original css shapes example (left) and with clipping applied (right)

I’d encourage you to experiment on your own. I maybe played around for half an hour at most to create everything I showed above plus quite a few more examples I didn’t show.

Again while css clipping and masking isn’t going to work in every browser, there isn’t much harm in using either as far as I can tell. Non-supporting browsers show the original element or image so you can clip and mask away in the name of progressive enhancement now if you’d like.

There’s one last topic I want to cover in regards to future css and that’s filtering. It’ll take more than a single post to cover and I’ll begin the discussion on Monday.

« »

Download a free sample from my book, Design Fundamentals.

One comment

Leave a Reply

Your email address will not be published.