Have you tried Flywheel? Learn moreJoin the best designers and creative agencies in the world. Learn more

How to use CSS and SVG clipping and masking techniques

How to use CSS and SVG clipping and masking techniques

SVGs are great for working on the web, and clipping and masking allow for some interesting ways to show or hide pieces of your web graphics. Using these techniques also allows for more flexibility with your designs because you do not have to manually make changes and create new images – it’s all done with code. By using a combination of CSS clipping and masking techniques, you will have lots of options for your website graphics.

To help clarify things, masking and clipping are two different ways you can manipulate images with CSS. Let’s start with clipping.

Clipping basics

If you’ve ever used Photoshop, you are probably already familiar with Clipping Masks. It’s a similar kind of approach. Clipping involves laying a vector shape, like a circle or a triangle, on top of an image or an element. Any part of the image behind the shape will be visible, while everything outside the boundaries of the shape will be hidden.

For example, if a triangle clipping mask is over the top of an image of a forest, you will see the forest image within the triangle shape. The shape’s boundary is called the clip path, not to be confused with the depreciated clip property. You create the clip path by using the clip-path property.


Remember: You should never make changes on a live site. Our free local development app, Local by Flywheel, will help you simplify your workflow and safely experiment with your site. Try it today!

Clipping in action

Clips are always vector paths. It can be confusing to understand, but anything outside the path will be hidden, while anything inside the path will be visible. To get a better understanding and to test this out yourself, see the sample on CodePen.


Here is a snippet of the HTML structure from the example:

<svg class="clip-svg">
		<clipPath id="polygon-clip-triangle-equilateral" clipPathUnits="objectBoundingBox">
			<polygon points="0 0.87, 0.5 0, 0.5 0, 1 0.87" />

This is the CSS to make the clipping happen:

.polygon-clip-triangle-equilateral {
	-webkit-clip-path: polygon(0% 87%, 50% 0%, 50% 0%, 100% 87%);
	clip-path: polygon(0% 87%, 50% 0%, 50% 0%, 100% 87%);
	-webkit-clip-path: url("#polygon-clip-triangle-equilateral");
	clip-path: url("#polygon-clip-triangle-equilateral");

You can see where the clipPath id is being referenced in the HTML and how it uses the clip-path URL to do the clipping.

Clippy tool

Clippy is a great tool to generate CSS clip paths. There are a wide variety of starter shapes and sizes that can be customized.


Masking basics

Masking is done using a PNG image, CSS gradient, or an SVG element to hide part of an image or another element on the page. We will be focusing on SVG graphics, but keep in mind this can be done with other image types or styles.

The mask property and mask element

Just a refresher to help visualize, it’s important to keep in mind that the masked element is the “original” (before mask is applied) image. You may not want to see the whole image, so hiding parts of it is done with the CSS mask property. The mask is the CSS shorthand for a group of individual properties, which we’ll dive into in a second. The SVG <mask> element is used inside an SVG graphic to add masking effects. In this example, the mask is a circle and there is also a gradient applied.

Using the SVG mask element on an SVG graphic

To get a feel for the SVG <mask> we will be masking with an SVG graphic.

It might be a bit complex at a first glance, but it all works together to mask the underlying image. We have an actual image as a background, so where does the SVG come into play? Unlike the clipping examples, this background image is technically inside of an SVG element. We’ll use CSS to apply this mask to the image. Properties will come from the SVG mask element, and we’ll give it the id of masked-element in our CSS.

To see this in  action, check out this Codepen sample. Here’s the working code for the masked SVG graphic:

<svg class="masked-element" width="300" height="300" viewBox="0 0 300 300">
	<image xlink:href="image link" width="300px" height="300px" />

css-svg-clipping-masking-masked-outline if you go to the Inspector, you can see the boundaries for the masked element. The circular shape is created with a mask.

With this CSS, we are specifying where to find the mask. It will look for the ID of #mask-this:

/* Here’s the CSS for masking */
.masked-element image {
  mask: url(#mask1);

Notice a gradient in the circle shape? A gradient has been applied, as well as setting the circle shape for the mask.

<svg class="svg-mask">
 		<mask id="mask1" maskUnits="objectBoundingBox" maskContentUnits="objectBoundingBox">
    <linearGradient id="grad" gradientUnits="objectBoundingBox" x2="0" y2="1">
      <stop stop-color="white" offset="0"/>
      <stop stop-color="green" stop-opacity="0" offset="1"/>
    <circle cx="0.50" cy="0.50" r="0.50" id="circle" fill="url(#grad)"/>

SVG text masking

Text masking can do some pretty cool things, such as showing an image through a text block. The good news is that a text element can be used inside of an SVG mask. As browser support increases in the future, this could be a really interesting way to combine images and typography.


Here’s a basic explanation of what is going on. There is an SVG text element inside the SVG mask. We’ve specified the RGB value for white, which creates the oval area around the masked text. Anything behind the oval area shows through the text, giving a cut-out feel.

<div class="text-wrap">
    <svg class="text-demo" viewBox="0 0 600 400" width="600" height="400">
      <mask id="myMask">
        <rect width="100%" height="100%" fill="#fff" />
        <text x="50" y="200" id="myText">My Text</text>
        <text x="125" y="293" id="mySubtext">SVG</text>
    <ellipse class="masked" cx="300" cy="200" rx="300" ry="150" fill="rgba(255, 255, 255, 0.8)" />

/* Here’s the CSS for text element */
#myText {
font-size: 125px;
font-style: bold;
fill: #000;

/* Here’s the CSS for masking */
.masked {
mask: url("#myMask");

To fully understand, it’s helpful to play around and experiment with the code. Try changing colors, changing text, and adjusting sizes in this Codepen.

The mask-image property

An image can be declared and the mask-image can be set to a URL value. The mask-image can be a PNG, SVG, or a reference to an SVG mask element, like I demonstrated in the previous example.

Because masking is used to partially or fully hide portions of an object or element, first you’ll want an image link to a file for the element that is going to be masked. Here’s what that image looks like. It’s colorful to make it very apparent which part the mask is showing and hiding.

<img class="mask-img example-mask" src="https://linktoimage.com/img/image-example.jpg" alt="Masked image">

So far there’s been a lot of SVG code, but this example is slightly different since there is going to be a raster image masked with an SVG.

.example-mask {
  mask-image: url(https://linktoimage.com/browser-icon-01.svg);
  webkit-mask-image: url(https://linktoimage.com/browser-icon-01.svg);
  mask-mode: alpha;
  webkit-mask-mode: alpha;
  mask-repeat: no-repeat;
  webkit-mask-repeat: no-repeat;
  mask-size: 200px;
  webkit-mask-size: 200px;
  mask-position: center;
  webkit-mask-position: center;

The mask-image property is where the mask shape will be declared. In this case, the mask image is an SVG graphic. Having the URL link included is how the mask is built.

Here it is on Codepen.

Combining multiple mask images

Just when you thought masking couldn’t get any better, there is the option to set more than one mask image layer. All you need to do is add two URL values (or more if you’re feeling ambitious) separated by a comma.

To expand on the simple mask from above, there will be an arrow added to the original graphic. Here’s how two masks are combined.

.combined-mask {
   mask-image: url(https://linktoimage.com/arrow-01.svg), url(https://linktoimage.com/browser-icon-01.svg);
  webkit-mask-image: url(https://linktoimage.com/arrow-01.svg), url(https://linktoimage.com/browser-icon-01.svg);

All you have to do is add the two values (with a comma) and now there are two combined masks, making the masking possibilities endless.

Here it is on Codepen.

Create a simple gradient with mask-image

Not all masks have to be a complex shape. Sometimes it’s not a particular image that is the mask, but rather a simple mask like a gradient. If you’re looking for a quick way to achieve this, the mask-image property is an option, which is pretty easy to implement.

In this example, there was a class applied to a gradient set as the mask-image property. With this simple declaration, it was easy to create a gradient mask on the image.

mask-image: linear-gradient(black, white, transparent);
-webkit-mask-image: linear-gradient(black, white, transparent);

See this on Codepen.

The mask-repeat property

Once you’ve created one mask, it’s pretty easy to make more. This really comes in handy if you’re looking to make a custom pattern. The mask-repeat property allows for repetition of the mask. If you’ve ever made a tiled background before, this is similar to that.

There are a few important things to keep in mind, like sizing and the type of mask-repeat that needs to be declared so the perfect pattern is created.

The mask-size is pretty easy to visualize, especially with the set pixel value here.

mask-size: 200px;
webkit-mask-size: 200px;

There are a few more mask-repeat options if you’re looking for a different effect for the pattern:

  • repeat-x repeats along the x coordinate.
  • Repeat-y repeats down the y coordinate.
  • space repeats and spreads out in the available area.
  • round repeats a number of times across the available area (scaling will help it fill the space if needed)

Browser support

Before committing to this new way of working with graphics, it’s important to note that browser support is not consistent with clipping and masking. Clipping is more supported than masking, but Internet Explorer does not fully support clipping. Current browser support for CSS masks is also fairly limited, so it’s suggested to be used as an enhancement on a few decorative elements. That way, if it is not supported by the user’s browser, it does not affect the content viewing experience.

To test things out and see if your masks and clippings are supported, I’d recommend making a JSFiddle or Codepen and then trying it in different browsers. Browser support has increased in the recent years, and it will eventually get to a point where it will be fully-supported. Don’t let the limitations get you down – it’s always good to be ahead of the game and once support is more mainstream, you will know exactly how to revolutionize your graphics. When in doubt, be sure to reference the trusted Can I Use.

After experimenting with these examples, this should provide a good introduction to masking and clipping. Although browser support is limited at this time, this will likely become a mainstream practice in the future. It’s always fun to think about how these techniques can be used to create interesting visuals. The future of web graphics will make us less dependent on image editors and allow for more effective ways to create and modify imagery directly in the browser.

This article was originally published on August 3rd, 2016. It was last updated on December 6th, 2017.


  • inspire says:

    Hi, is there a way to scale the image under the mask
    ( .masked-element image { mask: url(#mask1);} )

    but with keep original dimentions of the mask, when I am scaling the masked object ( .masked-element image ) – the mask defined in svg is seems to scaling too

  • That is really awesome content on how to use CSS and SVG clipping and masking techniques. Thanks a lot for sharing this nice content to us. Really helpful.

  • Jikku says:

    Is there a way to have SVG masks applied on regular HTML content?

Join the discussion

Share this article:
Get more great content in your inbox

More articles

Get content like this sent directly to your inbox!

Install WordPress locally free