The Magic of SVG Clip-path

alvarosabu

Alvaro Saburido

Posted on May 18, 2020

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

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

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

<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>
Enter fullscreen mode Exit fullscreen mode

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

Resources:

  • Background image here (You can also use any pic you prefer).
  • Svg Shape here.

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.

<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>
Enter fullscreen mode Exit fullscreen mode

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.

 <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>
Enter fullscreen mode Exit fullscreen mode

The result will be as awesome as this:

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.

<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>
Enter fullscreen mode Exit fullscreen mode

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:

(If you can't see the pen, click here)

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).

Can I Use Foreign Oject

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:

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

Were

.abstract-shape {
  clip-path: url(#mask);
}
Enter fullscreen mode Exit fullscreen mode


(If you can't see the pen, click here)

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

You guessed right, along with a lot of amazing stuff, css clip-path is not supported by Internet Explorer 💩 (Source caniuse).

Can I Use Foreign Object

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.

💖 💪 🙅 🚩
alvarosabu
Alvaro Saburido

Posted on May 18, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related