Cutouts

Avatar of Chris Coyier
Chris Coyier on

Take your JavaScript to the next level at Frontend Masters.

Ahmad Shadeed dug into shape “cutouts” the other day. Imagine a shape with another smaller shape carved out of it. In his typical comprehensive way, Ahmad laid out the situation well—looking at tricky situations that complicate things.

The first thing I’d think of is CSS’ clip-path, since it has that circle() syntax that seems like it a good fit, but no!, we need the opposite of what clip-path: circle() does, as we aren’t drawing a circle to be the clipping path here, but drawing all the way around the shape and then up into that second smaller circle and back out, like a bite out of a cookie. That puts us in clip-path: path() territory, which mercifully exists, and yet!, doesn’t quite get there because the path() syntax in CSS only works with fixed-pixel units which is often too limiting in fluid width layouts.

So that puts us at clip-path: url("#my-path"); (referencing an <svg> path), which is exactly where Ahmad starts this journey. But then he explores other options like a clever use of mask-image and a direct use of SVG <mask> and <image>, which turns out to be the winner.

Ideas like this have a weird way of entering the collective front-end developer consciousness somehow. Jay wrote up a very similar journey of wanting to do a shape cutout. Again, the problem:

clip-path defines a visible region, meaning that if you want all but a tiny chunk of the button to be visible, you need to define a path or polygon which is the inverse of the original. Here’s a demo of what I mean, using Clippy:

Jay Freestone, “Cutouts with CSS Masks”

In this case, polygon() has potential because it supports % units for flexibility (also, don’t miss Ana’s idea where the unit types are mixed within the polygon for a some-fixed-some-fluid concept).

Jay’s conclusion is that SVG has the most benefits of all the options:

[…] my overall impression is that mask-composite remains the more flexible solution, since it becomes trivial to use any SVG shape as the mask, not just a triangle or a simple polygon. The likelihood is that you’ll want to simply export an SVG and drop it in. Engineering the inverse result as clip-path is likely to get pretty hairy quickly.

Direct Link →