The Magic of SVG Clip-path
Tags: svg, css, webdev, tutorial
Published: 2020-05-18 07:00:38

---
canonical_url: https://alvarosaburido.com/blog/the-magic-of-svg-clip-path
---
My overall experience with SVG on web was pretty limited. Even considering that I had been delivering icons, vector-based illustrations, logos, and so on in this format for several years.

I have never dived into the amazing possibilities that **svg** brings along to implement customized layouts and forms until last month when the UX team of my project hand-off a beautiful layout for our client product.

I must say is one of the most amazing designs I have ever see, the whole page, colors, forms, **svg** lines swimming nicely on the backgrounds, truly transmit the brand's playful toyish spirit.

That also means, complexity. Tons of it, from the Frontend perspective, but who I'm to say no to an amazing challenge?. Having the plus of using Adobe's AEM and supporting IE11 (I know 😤).

![Challenge Accepted](https://media.giphy.com/media/GgcusW5RLS9Nu/giphy.gif)

Take this post as the result of how I approached the challenge of creating crazy masks for content with SVGs and what I learned in the process, I hope it will become a handful to you if you ever come to the same scenario and you need to implement such complexity in your layout.

## What is SVG?

SVG is an image format for vector graphics and it means **Scalable Vector Graphics**. It compresses nicely, you can scale to any size and you can control stuff like interactivity and applying filters easily.

![Svg Example](https://res.cloudinary.com/alvarosaburido/image/upload/v1589435907/blog/The%20Magic%20of%20SVG%20Clip-path/abstract-shape.png)

If you open the `svg` image in any IDE, you will notice that the file is actually in XML Format.

```xml
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
	<path d="M0,370.6c-0.5,35,29.5,68,60,82.8c40.8,19.7,82.2,6.8,99.3,1.4c76-23.8,83.3-81.4,130.3-79.9c43.9,1.4,53.2,52.1,102.2,52.5
		c38.6,0.3,67.2-30.9,79.9-44.6c44.4-48.3,49.5-116.9,33.1-165.5c-6-17.7-11.5-34.1-27.4-45.3c-30.9-22-62.5,2.7-96.2-16.2
		c-27.9-15.7-17.7-39-44.8-68c-44.9-47.9-125.5-40.2-155.5-37.3C145.6,53.7,101.3,58,66.5,92c-43.9,42.9-46.3,107.1-46.8,120.2
		c-1.7,45.2,14.1,62.2,1.4,103.6C12.1,345.6,0.3,348.8,0,370.6z"/>
	<path d="M373.8,89.9c2.7-4.9,14.3-24.5,37.4-30.2c5.6-1.4,18.5-4.6,30.9,2.2c18.8,10.2,20,33.9,20.2,38.1c0.1,3.2,0.6,21.6-8.6,25.9
		c-6.9,3.3-13-4.5-24.5-1.4c-7.4,1.9-7.1,5.7-13.7,7.9c-12.5,4.2-32-3.2-39.6-18.7C371.2,103.7,372.8,94,373.8,89.9z"/>
	<path d="M432.1,133.8c-4.2,1.6-9.3,6-8.6,10.8c0.7,5.5,8.7,9.2,15.1,7.9c6.7-1.4,12.4-8.5,10.8-13.7
		C447.7,133.4,438.5,131.3,432.1,133.8z"/>
</svg>
```

What is important for us here is the `<path />` because they are the ones responsible for the shape of the mask we are going to apply to an image.

## Using Clip-path

There are two ways you can use `clip-path`:

1. As an SVG element `<clip-path>` and an attribute `clip-path="url(#myMask)"`
2. As a CSS property.

### As an SVG element

For this example we are going to build something like this:

![Svg Masked Image](https://res.cloudinary.com/alvarosaburido/image/upload/v1589437180/blog/The%20Magic%20of%20SVG%20Clip-path/svg-masked-image_vifmwl.png)

Resources:

- Background image <a href="https://res.cloudinary.com/alvarosaburido/image/upload/v1589435086/blog/The%20Magic%20of%20SVG%20Clip-path/pic_yo5eyq.png" download>here</a> (You can also use any pic you prefer).
- Svg Shape <a href="https://res.cloudinary.com/alvarosaburido/image/upload/v1589437346/blog/The%20Magic%20of%20SVG%20Clip-path/shape_hjmncy.svg" download>here</a>.

Once you download the resources, let's start doing the markup:

First, we need to create an SVG object with the element `<clipPath />` inside of the `<defs>` element, this will contain the path defined by the `abstract-shape.svg` you just downloaded.

```xml
<svg xmlns="http://www.w3.org/2000/svg" style="position:absolute">
  <defs>
    <clipPath id="mask">
      <path
        d="M0,370.6c-0.5,35,29.5,68,60,82.8c40.8,19.7,82.2,6.8,99.3,1.4c76-23.8,83.3-81.4,130.3-79.9c43.9,1.4,53.2,52.1,102.2,52.5
          c38.6,0.3,67.2-30.9,79.9-44.6c44.4-48.3,49.5-116.9,33.1-165.5c-6-17.7-11.5-34.1-27.4-45.3c-30.9-22-62.5,2.7-96.2-16.2
          c-27.9-15.7-17.7-39-44.8-68c-44.9-47.9-125.5-40.2-155.5-37.3C145.6,53.7,101.3,58,66.5,92c-43.9,42.9-46.3,107.1-46.8,120.2
          c-1.7,45.2,14.1,62.2,1.4,103.6C12.1,345.6,0.3,348.8,0,370.6z"
      />
      <path
        d="M373.8,89.9c2.7-4.9,14.3-24.5,37.4-30.2c5.6-1.4,18.5-4.6,30.9,2.2c18.8,10.2,20,33.9,20.2,38.1c0.1,3.2,0.6,21.6-8.6,25.9
          c-6.9,3.3-13-4.5-24.5-1.4c-7.4,1.9-7.1,5.7-13.7,7.9c-12.5,4.2-32-3.2-39.6-18.7C371.2,103.7,372.8,94,373.8,89.9z"
      />
      <path
        d="M432.1,133.8c-4.2,1.6-9.3,6-8.6,10.8c0.7,5.5,8.7,9.2,15.1,7.9c6.7-1.4,12.4-8.5,10.8-13.7
          C447.7,133.4,438.5,131.3,432.1,133.8z"
      />
    </clipPath>
  </defs>
</svg>
```

It's very important that we assign an `id` to the `<clipPath />` element, this is the way we are going to reference it later to apply the mask.

For the image, `svg` has an element dedicated to it `<image>`, the magic happens when we add the attribute `clip-path="url(#mask)"` Here is where we add the id we mention above.

```xml
 <svg  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 506" >
    <image id="image" class="image__svg-image" width="100%" height="100%" clip-path="url(#mask)" x="-100px" xlink:href="https://res.cloudinary.com/alvarosaburido/image/upload/v1589435086/blog/The%20Magic%20of%20SVG%20Clip-path/pic_yo5eyq.png" />
</svg>
```

The result will be as awesome as this:
![](https://res.cloudinary.com/alvarosaburido/image/upload/v1589787537/blog/The%20Magic%20of%20SVG%20Clip-path/Svg_Clip-Path_Mask_and_The_Magic_of_SVG_Clip-path_-_DEV_Community__a4jmqn.png)

{% codepen https://codepen.io/alvarosaburido/pen/YzyzGvM %}

## What about video?

This approach is also applicable to videos, or any other content (embedded views), but you will need to insert it inside an SVG `<foreignObject />` tag.

The `<foreignObject>` SVG element includes elements from a different XML namespace. In the context of a browser, it is most likely `(X)HTML`.

```xml
<svg  xmlns="http://www.w3.org/2000/svg" viewBox="0 0 814 506">
  <foreignObject clip-path="url(#mask)" width="814" height="800">
      <iframe width="640" height="480" src="https://www.youtube.com/embed/oAuVf1coSjs" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
  </foreignObject>
</svg>
```

You get a similar effect ut with more dynamic content inside, you will probably will need to fight a little bit with the `width` and `height` of the element so it all fits on their site. You should end up with something similar to:

{% codepen https://codepen.io/alvarosaburido/pen/pojOgJQ %}

(If you can't see the pen, click [here](https://codepen.io/alvarosaburido/pen/pojOgJQ))

Consider also that shape form may affect access to video controls for example, so this one may not be the perfect choice for videos.

But wait... will this work in Internet Explorer 💩? You guessed right, `<foreignObject>` is not supported for any Internet Explorer version... who would it guess 🙄 (Source [caniuse](https://caniuse.com/#feat=mdn-svg_elements_foreignobject)).

![Can I Use Foreign Oject](https://res.cloudinary.com/alvarosaburido/image/upload/v1589480543/blog/The%20Magic%20of%20SVG%20Clip-path/can-i-use-foreign-object.png)

## As a CSS property

You can also achieve the same effect using `clip-path` as a CSS property, the SVG containing the `<ClipPath>` should remain the same, but for the image or video instead of also using SVG, you can use a normal HTML element like `img` or `video`.

Having that in mind, let's remove the svg element with the image/video and substitute it with something like this:

```html
<img
  class="abstract-shape"
  src="https://res.cloudinary.com/alvarosaburido/image/upload/v1589435086/blog/The%20Magic%20of%20SVG%20Clip-path/pic_yo5eyq.png"
  alt=""
/>
```

Were

```css
.abstract-shape {
  clip-path: url(#mask);
}
```

{% codepen https://codepen.io/alvarosaburido/pen/NWGLgwg %}
(If you can't see the pen, click [here](https://codepen.io/alvarosaburido/pen/pojOgJQ))

Of course, this would have been my choice by preference, is so much cleaner than using the SVG elements, also easier to calibrate the position of the image to get the best result, but then 🤦‍♂...

![Horrible IE](https://res.cloudinary.com/alvarosaburido/image/upload/v1589523497/blog/The%20Magic%20of%20SVG%20Clip-path/eww-internet-explorer_mtabxm.gif)

You guessed right, along with a lot of amazing stuff, css `clip-path` is not supported by Internet Explorer 💩 (Source [caniuse](https://caniuse.com/#feat=css-clip-path)).

![Can I Use Foreign Object](https://res.cloudinary.com/alvarosaburido/image/upload/v1589523051/blog/The%20Magic%20of%20SVG%20Clip-path/css-clip-path-caniuse_oeivpn.png)

## Conclusion

Wrapping up my experience creating crazy forms for a layout, this is what I learned:

- SVG is very versatile, you don't only have `clip-path` you can also define filters and animations inside of `<defs>` that would make your markup even richer.
- SVG is mostly well supported in browsers,
- Nothing cool works on IE 💩. So for your mental health and your users, stop using Internet Explorer or change to Microsoft Edge at least.

That's all for today folks! Keep rocking those SVG and drop some comments in the section below if you enjoy the article.