Cutting the box: clipping images and elements with CSS

Every element on a webpage lives inside a rectangular box, but that does not mean it has to look like one. The CSS clip-path property lets you cut away parts of an image or another element to create interesting shapes and effects.

How clipping works

In the example above, the balloon image is square (source). By applying the basic shape value of circle() to clip-path, the sky around the balloon is clipped away, leaving only a circular image on the page.

When the image is a link, clipping also has an effect on interaction: only the visible area can be clicked, because events do not fire on hidden parts of an element. Clipping can be applied to any HTML element, and there are several ways to define the clipped area.

Basic shapes

The clip-path property accepts a range of values. The initial example used circle(), one of the basic shape values defined in the CSS Shapes specification. The same values can also be used with shape-outside to make text flow around the shape.

The complete list of basic shapes:

inset()

The inset() value cuts the clipped area in from the edges of the element. You can pass values for the top, right, bottom, and left edges, and use the round keyword to add a border-radius and curve the corners of the clipped area.

circle()

The circle() value defines a circular clipped area. The first argument is a length or percentage representing the radius of the circle, while an optional second argument sets the center. Keyword values such as top right can be used for positioning, or lengths and percentages.

Watch out for flat edges

A caution applies to all these values: the shape is clipped by the element's margin box. If a circle on an image extends beyond the natural size of the image, you end up with a flat edge. For instance, to put a circle in the top right of an image:

A clipped circle with flat edges
The image used earlier now has circle(50%) applied. As the image is not square, we hit the margin box at the top and bottom and the circle is clipped.

ellipse()

An ellipse behaves like a squashed circle. It accepts a radius for the x-axis and another for the y-axis, plus a value for the center of the ellipse.

polygon()

The polygon() value allows for more complex shapes by defining coordinates for as many points as needed. For help creating polygons, tools like Clippy, a clip-path generator, let you visually build shapes and copy the resulting code into your project.

Box values

CSS Shapes also defines shapes from box values, which map to the CSS Box Model: content-box, padding-box, border-box, and margin-box.

These values can be used on their own or combined with a basic shape to define the reference box the shape uses. For example, clipping to the edge of the content:

.box {
  clip-path: content-box;
}

In this example, the circle uses the content-box as its reference box instead of the default margin-box:

.box {
  clip-path: circle(45%) content-box;
}

Note that browsers do not currently support box values for the clip-path property, though they are supported for shape-outside.

Using an SVG element

For more control than basic shapes allow, you can use an SVG clipPath element. Reference the SVG by its ID using url() as the value for clip-path.

Animating the clipped area

CSS transitions and animations can also be applied to clip-path. For instance, you can animate a circle on hover by transitioning between two circles with different radius values. There are many creative ways to incorporate animation with clipping; Animating with clip-path on CSS Tricks runs through further ideas.

Feature detection

clip-path is supported in Chrome 55, Firefox 3.5, Safari 9.1, and Edge 79. For legacy browsers, a fallback is to let the browser ignore the clip-path property and show the unclipped image. If that leaves an unacceptable layout, you can test for support using a feature query and offer an alternate layout:

@supports(clip-path: circle(45%)) {
  /* code that requires clip-path here. */
}

Photo by Matthew Henry on Burst.