Clipping the path fantastic

Create responsive shapes with clip-path and break out of the box

The CSS clip-path property is your ticket to shape-shifting the monotonous, boxy layouts traditionally associated with flat, responsive design. You begin to think out of the box, literally, and hexagons, stars and octagons begin to take form in your web pages. Once you get your hands dirty with clip-path, there's no end to the shapes you can generate, simply by tweaking a few values.

While the focus of this article is on clip-path using polygons with CSS, all the demos provide a reference to an inline SVG, in order to gain additional support on Firefox. Once you have created a responsive shape via CSS clip-path, it's trivial to create a responsive SVG clipped shape. We'll look at this in detail later.

Clip-path, in a nutshell

Clipping, through the clip-path property, is akin to cutting a shape (like a circle or a pentagon) from a rectangular piece of paper. Clip-path belongs to the CSS Masking Module Level 1 specification. The spec states that "CSS Masking provides two means for partially or fully hiding portions of visual elements: masking and clipping."

The first part, i.e. masking, concerns itself with using a graphical element like a PNG image, CSS gradient or an SVG element as a mask to conceal sections of another element.

The second part, i.e. clip-path, uses a closed vector path that could be a basic shape defined in CSS or an SVG using the clipPath tag. The region inside this path is displayed and everything beyond or outside it is clipped out.

Note: Masking is out of the scope of this article, but you can read more here and here.

Below is a simple visualization of how clip-path works:

Image source here.

Note: The demos in this article, including the one above, will work in Firefox and Webkit/Blink browsers like Chrome, Safari and Opera.

Clip-path is not clip

There is an older CSS 2.1 clip property, that is rather restricted, notably because it supports only a rectangular shape. It has been deprecated in favor of clip-path.

Articles about clipping that use the old, deprecated syntax will feature code that looks like this:

.element { clip: rect(30px, 30px, 20px, 20px); }

Support for clip-path

In August 2014, the CSS Masking Module was published as a Candidate Recommendation, which is a step up from the earlier Last Call Working Draft stage. Before we look at browser support, it's important to look at the multiple ways in which clip-path can be applied to an element, since browser support varies for each method.

There are two ways to use clip-path:

  1. With CSS: Basic shapes from the CSS Shapes Module provide a convenient way to use clip-path. The different shapes available are polygon, circle, ellipse and inset. Inset is for rectangular shapes.
  2. With SVG: One can, alternatively, create a shape using SVG and then clip an element to this shape via the URL syntax.
    There are two ways to do this:
    • A reference to an inline SVG i.e. the SVG markup exists on the page itself
    • A reference to an external SVG document
    In both cases, the clipPath element within the SVG is used to wrap the element that determines the clipping path, be it a circle, polygon, path or other element.
    Compare the demo below in Firefox and a Webkit/Blink browser like Chrome to spot the differences. Square images imply a lack of browser support.

As you may have garnered from observing the above demo in different browsers, support for clip-path is quirky and currently depends on the means you choose to clip an element.

With CSS

Chrome 24+, Safari 7+, Opera 15+, iOS 7.1+, Android 4.4+, Opera Mobile 24+

Note: All of the supported browsers currently require the -webkit vendor prefix.

With SVG

All of the above browsers and Firefox 3.5+.

Clip-path is not yet supported in Internet Explorer, but is currently under consideration as part of the Masking Module.

Note: There is a caveat with SVG clipping path support. Modern Webkit/Blink browsers support clipping paths with SVGs only if they are declared inline (i.e. within the document). References to external SVGs are only supported in Firefox, as is evinced in the demo above. See this link on the Chromium bug tracker for more.

Browser support source here.

Let's examine the advantages of CSS vis-a-vis SVG with clip-path.

Advantages: CSS:

Advantages: SVG:

While CSS offers a background-clip property that provides us with some options (including a non-standard way to clip text), neither background-clip nor CSS clip-path can match up to what SVG clipping can achieve in modern browsers. Getting acquainted with clip-path via CSS, however, is a less intimidating approach, initially (and especially if you aren't familiar with manipulating SVGs), and prepares one for the intricacies of clipping paths with SVG, as well as the CSS Shapes Module, where content aligns itself to the shape of an element.

Note: If you can't wait to delve into the matrix of clipping with SVG, Sara Soueidan's article makes for a good starting point.

Let's look at the pros and cons of using clip-path to progressively enhance our designs:


  1. Browsers that don't support the clip-path property will ignore it; if used with care, users on non-supporting browsers won't suspect a thing!
  2. Once a clipping path shape is generated, the spec states that pointer events must not be dispatched outside the clipping area (which is ideal). So the click event is restricted to the shape and its outer boundary. We will look at this in the demos below.
  3. You can use percentages or any length unit like pixels and ems to define your coordinates with basic shapes using CSS. Fluid units like percentages can be used to create responsive shapes — perfect for adaptive layouts.


  1. All borders, shadows and outlines outside the clipping region are clipped. You can't add a border and expect it to be honored. We'll look at some alternatives below.
  2. The spec has not yet reached Recommendation, so there's always the chance that the syntax will change in the interim.
  3. A few bugs have been reported with clip-path and 3D transforms, transitions and opacity, which are covered in the demos below. It's best to be aware of these and avoid combining properties that replicate these bugs.

Clip-path with polygons: usage and syntax

The demos below focus on using different kinds of polygons in your designs. The syntax for the other basic shapes, i.e. inset, circle and ellipse is quite simple, and there's only so far you can go with them. Polygons, however, open the door to practically an infinite numbers of shapes.

The syntax for a basic polygon shape is:

.element {clip-path: polygon(x1 y1, x2 y2, x3 y3, ...);}

Each pair argument in the list represents the x-axis and y-axis coordinates of that particular vertex of the polygon.

Here's how we'd write it in the real world (minus the currently supported Webkit prefixed version):

.element {clip-path: polygon(0 100%, 0 0, 100% 0, 80% 100%);}

Let's add support for Firefox, with a reference to an inline SVG:

.element {clip-path: url("#clip-shape");}

Here's how our selector finally looks, with cross-browser support:

.element {
  -webkit-clip-path: polygon(0 100%, 0 0, 100% 0, 80% 100%);
  clip-path: polygon(0 100%, 0 0, 100% 0, 80% 100%);
  -webkit-clip-path: url("#clip-shape");
  clip-path: url("#clip-shape");

Below is the code for the inline SVG, that we will need to insert anywhere in the markup.

<svg width="0" height="0">
	<clipPath id="clip-shape" clipPathUnits="objectBoundingBox">
	  <polygon points="0 1, 0 0, 1 0, 0.8 1" />

Here is the final demo.

Link here

You can create a responsive SVG clipping path in the following manner:

Read more about this process here.

Let's look at a demo to understand how to plot coordinates for a polygon.

Below we have an image that is clipped. The background color represents the dimensions of the original image. The black boxes with the coordinates are simply absolutely positioned divs whose locations match the polygon vertices in percentages. You will see how they maintain their positions, even if you resize your browser window to a narrow width (e.g. > 400px).

x, y1
x2 y2
x3 y3
x4 y4
.element {clip-path: polygon(50% 0%, 90% 10%, 90% 90%, 10% 90%);}

Real world examples with clip-path

Note: Every demo in this article uses clip-path with CSS, but also has an inline SVG in the markup with a class of clip-svg, which simply resets the width and height of the SVG to zero. You could alternatively, remove the class and set the width and height attributes directly in the SVG markup.

Example 1: Let's clip an image to various polygon shapes.

Quick definition for a polygon: A 2D shape, that's closed, and made of straight lines.
Therefore, a shape cannot be a polygon if it fulfills any one of the following conditions: has curves, is open, or has less than 3 lines. Some famous polygons in history include triangles, quadrilaterals, pentagons and hexagons. Even star shapes are polygons, since the boundaries of a polygon can cross itself.

Note: The images in the demo are responsive. By using the good old responsive image solution img {max-width: 100%; height: auto;} and adaptive clip paths via CSS and SVG, our polygons blissfully scale up and down.

This demo is the result of an exercise to understand plotting coordinates to make polygon shapes. I've added several shapes that you can use for your designs in the demo below. On hovering over each image, you can see the aspect ratio of the original image.

Do note that nothing beats the exceptional Clippy, a GUI tool by Bennett Feely to visualize shapes. All coordinates for all the existing shapes are provided in percentages and there's also a custom polygon option. This one's a game changer. You can use Clippy to generate clipped shapes and create SVGs based on them yourself, for better browser support.

Example 2: Let's animate a basic shape via a CSS transition

Hover over the purple hexagon. It transforms to an octagon on hover. However, the CSS transition specified has not taken effect.

The reason for this is explained in Sara Soueidan's article on animating CSS shapes — "The number of points defining the final shape must be the same as the number of points defining the initial shape." Makes perfect sense!

Since the hexagon has 6 pairs of coordinate points, let's add 2 extra pairs through duplication to make it 8, i.e. to match the numbers for an octagon. These duplicated pairs won't affect the shape of the hexagon.

Hexagon: default polygon with 6 pairs of coordinate points:

clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);

Hexagon: polygon with 8 pairs of coordinate points; the first 2 pairs have been duplicated:

clip-path: polygon(50% 0%, 50% 0%, 100% 25%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);

Now we have a smooth transition as the shapes transform, as seen in the demo below.
Background image source here.

Note: For browsers that support clipping paths only with SVG (currently Firefox), we need to add a SMIL animation to obtain a seamless transition on hover. As part of the SMIL spec, declarative animations can be used to animate paths and polygon points in SVG, which is currently impossible with CSS. Keep in mind that there are discussions to deprecate SMIL from Chrome and Chromium, and drive focus towards implementing the Web Animations API, which is unfortunately at an early draft stage.

In the demo below, you can see that we have animated the polygon points between the mouseover and mouseout events over a duration of 0.2 seconds. Look for the <animate> tag inside the SVG markup.

Link here

Example 3: Let's add a border to a clipped object

To cut a long story short, borders, outlines and box-shadows that lie outside the clipping region are removed.

I was a little saddened by this, and pinged the W3 members on the working group for CSS, but the conclusion is that there's no way to do this when you're using basic shapes. Dirk Schulze responded to my query — "Yes, all drawing operations belonging to the element get clipped, this includes outlines and borders."

See the demo below. You can hover over the rhomboid with a partial border to see the original, unclipped version with the entire border.

Of course, we can always use a CSS hack to get a border, which is what I finally resorted to — good old generated content.

The demo below creates a copy of the element using pseudo-elements via content:after and absolutely positions it. This creates the illusion of borders, and allows us to simulate interesting effects like the gradient border, as seen in the second octagon and an inset box-shadow using a CSS filter (not very pretty, but functional) on the third one. Do note that CSS filters currently work only in Firefox and Webkit/Blink browsers.

Link here

Example 4: Let's use clip-path to create a diamond grid with a rhombus shape

Below is the image we will use.


This is the effect we're aiming for. On hovering over the bottom three boxes, the background color fades to reveal the background.


The actual size of the image is 600 x 600 pixels. Hence, let's start with four empty divs of 300px each and apply the same background image to them. Let's add a parent wrapper of 604px and layout the images with the inline-block property.


We will now change the value of the background position for each image to top, left, right and bottom respectively.


Let's clip each box to a rhombus shape. We will add an absolutely positioned overlay over each of the bottom 3 images, with some text.


Now we will move the images into rows, the second and third image into 1 row, and the first and fourth into individual rows.


Finally, we will use negative margins to push up the second and third rows, so they are laid out as in the final demo below. We can remove the width value of 604px on the parent wrapper, and structure our media query, so the 4 diamond boxes moved from a stacked layout on smaller screens to inline-block on larger ones.

Link here

While working on this demo, I noticed a bug on Chrome with pointer-events being dispatched outside the clipped region, which is in violation of what the spec says, i.e. "By default, pointer events must not be dispatched on the clipped-out (non-visible) regions of a shape."
I have filed a bug here. The issue with this demo was solved by using the pointer-events property with the none value on the overlay. Alternatively, you could apply the same clip-path value to the overlay, to resolve the issue.

Due to the negative margins applied, this demo would look odd on browsers that don't support clip-path. You would have to use some sort of feature detection to apply the margins (although I haven't experimented with the same) or an @supports CSS feature query, although I wouldn't recommend the latter in production code.

Example 5: Let's create a dummy profile page with hexagon shapes

Our final page should look like this:


We start by adding a background image of hexagon tiles to the body. (Image source here).

The hexagon clip-path values can be obtained from one of the demos above or with the Clippy tool.

The first hexagon uses a background image (since I'm blending a dull maroon colour into the background using the background-blend-mode property.). Using generated content, an absolutely positioned overlay is clipped to a maroon triangle shape, that you can see on the bottom. It disappears on hover.

The second hexagon with the word "work" simply has a black background color that changes on hover.

The third hexagon has a gradient border, similar to the one in the demo on achieving borders with clip-path.

The hexagons stack on smaller screens, and are vertically centered on larger ones. I've used a combination of display: table and the absolute centering transforms hack, but of course, you could use flexbox, floats or whatever floats your layouting boat.

Here's the final demo.

Link here

I discovered a bug with clip-path while creating this demo. You can see it here. The combination of altering the opacity value with a CSS transition causes a flicker and artifacts on the page. It's good to be aware of this if you're using clip-path to progressively enhance your designs.

There is also a bug with clip-path and the backface-visibility property when set to hidden. This bug is documented on the Chromium issue tracker and I have been able to replicate it using the basic shape syntax on Chrome on Linux. Keep this in mind if you're using a clip-path shape to do a cool 3D flip or anything that uses CSS 3D transforms.

While clipping with SVG wins hands down for the flexilibity and options it provides, nothing beats the ease with which elements can be clipped with CSS. In fact, the same polygon coordinates can be effortlessly recycled to create a responsive SVG, for even better browser support. With clip-path, you can dramatically alter the look and feel of a page, without worrying too much about non-supporting browsers, where it gracefully degrades. If you choose to use clip-path for design enhancements, do keep an eye on the spec, as it advances towards Recommendation.

Resources, Tools and Inspiration


The W3C spec for CSS Masking

The ultimate source of truth and the best reference, when in doubt.

Clipping in CSS and SVG

The definitive guide to clipping paths. While the focus is largely on SVG, Sara Soueidan's article is a fantastic introduction, with plenty of information for intermediate and advanced readers as well.


Sara Soueidan's well-researched and comprehensive article breaks down a fairly complicated module into something that is easy is to understand and assimilate.

Clipping and Masking in CSS

Chris Coyier's article, peppered with several helpful demos, enumerates on both clipping and masking.


Clippy: A clip-path maker

A fab tool to generate a plethora of predefined and custom polygon shapes, circles, ellipses for CSS clip-path. All values are in percentages and hence useful for responsive layouts.

Clip path generator

A rather comprehensive graphical interface to clip or mask an element. Provides cross browser support for Firefox, Chrome, Safari and old iOS. Clips in pixels and not percentages.


Species in Pieces

So breathtaking it borders on the spiritual. A showcase of 30 endangered species, entirely crafted with CSS clip-path, without a hint of Canvas or WebGL. Watch in a Webkit/Blink browser, till the other ones catch up.