Using CSS Clip Path to Create Interactive Effects, Part II

Avatar of Mikael Ainalem
Mikael Ainalem on

This is a follow up to my previous post looking into clip paths. Last time around, we dug into the fundamentals of clipping and how to get started. We looked at some ideas to exemplify what we can do with clipping. We’re going to take things a step further in this post and look at different examples, discuss alternative techniques, and consider how to approach our work to be cross-browser compatible.

One of the biggest drawbacks of CSS clipping, at the time of writing, is browser support. Not having 100% browser coverage means different experiences for viewers in different browsers. We, as developers, can’t control what browsers support — browser vendors are the ones who implement the spec and different vendors will have different agendas.

One thing we can do to overcome inconsistencies is use alternative technologies. The feature set of CSS and SVG sometimes overlap. What works in one may work in the other and vice versa. As it happens, the concept of clipping exists in both CSS and SVG. The SVG clipping syntax is quite different, but it works the same. The good thing about SVG clipping compared to CSS is its maturity level. Support is good all the way back to old IE browsers. Most bugs are fixed by now (or at least one hope they are).

This is what the SVG clipping support looks like:

This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.

Desktop

ChromeFirefoxIEEdgeSafari
4311123.2

Mobile / Tablet

Android ChromeAndroid FirefoxAndroidiOS Safari
1221234.43.2

Clipping as a transition

A neat use case for clipping is transition effects. Take The Silhouette Slideshow demo on CodePen:

See the Pen Silhouette zoom slideshow by Mikael Ainalem (@ainalem) on CodePen.

A “regular” slideshow cycles though images. Here, to make it a bit more interesting, there’s a clipping effect when switching images. The next image enters the screen through a silhouette of of the previous image. This creates the illusion that the images are connected to one another, even if they are not.

The transitions follow this process:

  1. Identify the focal point (i.e., main subject) of the image
  2. Create a clipping path for that object
  3. Cut the next image with the path
  4. The cut image (silhouette) fades in
  5. Scale the clipping path until it’s bigger than the viewport
  6. Complete the transition to display the next image
  7. Repeat!

Let’s break down the sequence, starting with the first image. We’ll split this up into multiple pens so we can isolate each step.

Silhouette zoom slideshow explained I by Mikael Ainalem (@ainalem) on CodePen.

This is the basic structure of the SVG markup:

<svg>
  ...
  <image class="..." xlink:href="..." />
  ...
</svg>

For this image, we then want to create a mask of the focal point — in this case, the person’s silhouette. If you’re unsure how to go about creating a clip, check out my previous article for more details because, generally speaking, making cuts in CSS and SVG is fundamentally the same:

  1. Import an image into the SVG editor
  2. Draw a path around the object
  3. Convert the path to the syntax for SVG clip path. This is what goes in the SVG’s <defs> block.
  4. Paste the SVG markup into the HTML

If you’re handy with the editor, you can do most of the above in the editor. Most editors have good support for masks and clip paths. I like to have more control over the markup, so I usually do at least some of the work by hand. I find there’s a balance between working with an SVG editor vs. working with markup. For example, I like to organize the code, rename the classes and clean up any cruft the editor may have dropped in there.

Mozilla Developer Network does a fine job of documenting SVG clip paths. Here’s a stripped-down version of the markup used by the original demo to give you an idea of how a clip path fits in:

<svg>
  <defs>
    <clipPath id="clip"> <!-- Clipping defined -->
      <path class="clipPath clipPath2" d="..." />
    </clipPath>
  </defs>
  ...
  <path ... clip-path="url(#clip)"/> <!-- Clipping applied -->
</svg>

Let’s use a colored rectangle as a placeholder for the next image in the slideshow. This helps to clearly visualize the shape that part that’s cut out and will give a clearer idea of the shape and its movement.

Silhouette zoom slideshow explained II by Mikael Ainalem (@ainalem) on CodePen.

Now that we have the silhouette, let’s have a look at the actual transition. In essence, we’re looking at two parts of the transition that work together to create the effect:

  • First, the mask fades into view.
  • After a brief delay (200ms), the clip path scales up in size.

Note the translate value in the upscaling rule. It’s there to make sure the mask stays in the focal point as things scale up. This is the CSS for those transitions:

.clipPath {
  transition: transform 1200ms 500ms; /* Delayed transform transition */
  transform-origin: 50%;
}

.clipPath.active {
  transform: translateX(-30%) scale(15); /* Upscaling and centering mask */
}

.image {
  transition: opacity 1000ms; /* Fade-in, starts immediately */
  opacity: 0;
}

.image.active {
  opacity: 1;
}

Here’s what we get — an image that transitions to the rectangle!

Silhouette zoom slideshow explained III by Mikael Ainalem (@ainalem) on CodePen.

Now let’s replace the rectangle with the next image to complete the transition:

Silhouette zoom slideshow explained IV by Mikael Ainalem (@ainalem) on CodePen.

Repeating the above procedure for each image is how we get multiple slides.

The last thing we need is logic to cycle through the images. This is a matter of bookkeeping, determining which is the current image and which is the next, so on and so forth:

remove = (remove + 1) % images.length;
current = (current + 1) % images.length

Note that this examples is not supported by Firefox at the time of writing because is lacks support for scaling clip paths. I hope this is something that will be addressed in the near future.

Clipping to emerge foreground objects into the background

Another interesting use for clipping is for revealing and hiding effects. We can create parts of the view where objects are either partly or completely hidden making for a fun way to make background images interact with foreground content. For instance, we could have objects disappear behind elements in the background image, say a building or a mountain. It becomes even more interesting when we pair that idea up with animation or scrolling effects.

See the Pen Parallax clip by Mikael Ainalem (@ainalem) on CodePen.

This example uses a clipping path to create an effect where text submerges into the photo — specifically, floating behind mountains as a user scrolls down the page. To make it even more interesting, the text moves with a parallax effect. In other words, the different layers move at different speeds to enhance the perspective.

We start with a simple div and define a background image for it in the CSS:

Parallax clip Explained I by Mikael Ainalem (@ainalem) on CodePen.

The key part in the photo is the line that separates the foreground layer from the layers in the background of the photo. Basically, we want to split the photo into two parts — a perfect use-case for clipping!

Let’s follow the same process we’ve covered before and cut elements out by following a line. In your photo editor, create a clipping path between those two layers. The way I did it was to draw a path following the line in the photo. To close off the path, I connected the line with the top corners.

Here’s visual highlighting the background layers in blue:

Parallax clip Explained II by Mikael Ainalem (@ainalem) on CodePen.

Any SVG content drawn below the blue area will be partly or completely hidden. This creates an illusion that content disappears behind the hill. For example, here’s a circle that’s drawn on top of the blue background when part of it overlaps with the foreground layer:

Parallax clip Explained III by Mikael Ainalem (@ainalem) on CodePen.

Looks kind of like the moon poking out of the mountain top!

All that’s left to recreate my original demo is to change the circle to text and move it when the user scrolls. One way to do that is through a scroll event listener:

window.addEventListener('scroll', function() {
  logo.setAttribute('transform',`translate(0 ${html.scrollTop / 10 + 5})`);
  clip.setAttribute('transform',`translate(0 -${html.scrollTop / 10 + 5})`);
});

Don’t pay too much attention to the + 5 used when calculating the distance. It’s only there as a sloppy way to offset the element. The important part is where things are divided by 10, which creates the parallax effect. Scrolling a certain amount will proportionally move the element and the clip path. Template literals convert the calculated value to a string which is used for the transform property value as an offset to the SVG nodes.

Combining clipping and masking

Clipping and masking are two interesting concepts. One lets you cut out pieces of content whereas the other let’s you do the opposite. Both techniques are useful by themselves but there is no reason why we can’t combine their powers!

When combining clipping and masking, you can split up objects to create different visual effects on different parts. For example:

See the Pen parallax logo blend by Mikael Ainalem (@ainalem) on CodePen.

I created this effect using both clipping and masking on a logo. The text, split into two parts, blends with the background image, which is a beautiful monochromatic image of the New York’s Statue of Liberty. I use different colors and opacities on different parts of the text to make it stand out. This creates an interesting visual effect where the text blends in with the background when it overlaps with the statue — a splash of color to an otherwise grey image. There is, besides clipping and masking, a parallax effect here as well. The text moves in a different speed relative to the image when the user hovers or moves (touch) over the image.

To illustrate the behavior, here is what we get when the masked part is stripped out:

parallax logo blend Explained I by Mikael Ainalem (@ainalem) on CodePen.

This is actually a neat feature in itself because the text appears to flow behind the statue. That’s a good use of clipping. But, we’re going to mix in some creative masking to let the text blend into the statue.

Here’s the same demo, but with the mask applied and the clip disabled:

parallax logo blend Explained II by Mikael Ainalem (@ainalem) on CodePen.

Notice how masking combines the text with the statue and uses the statue as the visual bounds for the text. Clipping allows us to display the full text while maintaining that blending. Again, the final result:

See the Pen parallax logo blend by Mikael Ainalem (@ainalem) on CodePen.

Wrapping up

Clipping is a fun way to create interactions and visual effects. It can enhance slide-shows or make objects stand out of images, among other things. Both SVG and CSS provide the ability to apply clip paths and masks to elements, though with different syntaxes. We can pretty much cut any web content nowadays. It is only your imagination that sets the limit.

If you happen to create anything cool with the things we covered here, please share them with me in the comments!