Making Sense of Clip Path

One of the great parts about teaching, is that students come in with the freshest ideas. Those of us in the industry tend to over think how we would accomplish a task and thus, miss out on all the cool new techniques available.

Enter the first week project from our Bootcamp. A single page website that demonstrates comprehension of HTML and CSS: semantic usage of markup and CSS to achieve presentational styling. One of our students, Heather Banks, who had previously taken the part-time HTML/CSS as my student, wanted to replicate an effect seen on Squarespace, where the surrounding div appeared to have a cut in it.

Knowing that with her previous experience, the HTML and CSS of the site was completely within her skill level, I embarked on helping to achieve the effect. Making it appear that the nav is being clipped is no easy task, and my first instinct was to have a create an image that matches the portion of the background being cropped and set it as an after element. Problem is that it’s the least responsive fix out there and not entirely manageable.

Enter the CSS property clip-path.

This little used guy is part of a working draft that provides tools to hide portions of elements via masking and clipping. While clip-path is still not widely supported by all major browsers (c’mon Firefox and IE), it is a great little tool to achieve stylish effects on Webkit browsers.

Note, we need to use -webkit in order to use within these browsers currently.

Simply the way it works is to provide a series of X and Y values to create a path. These values, when used to create a full path, clip the image inside to the dimensions of the path.

We can create many different shapes from circles, ellipsis, polygons. Creativity is the only limit.

A simple triangle clip

View the code on codepen

The above effect is achieved by simply using one element applying a clip-path to it.

.clipClass {
-webkit-clip-path: polygon(0 100%, 50% 0, 100% 100%);
}

Whoa, Let’s break this down.

Much like the positioning property, we need to think in X and Y values. X:0 and Y:0 starts in the top left corner of the element and moves from there. X:100% refers to the right side and Y:100% refers to the bottom of the element.

Got it, cool. So the path we created above creates the following points.

x: 0, y:100%
x: 50%, y: 0
x: 100%, y: 100%

A simple path that starts in the bottom left, moves horizontally 50% and heads to the top, then goes 100% of the way through the element horizontally and sticks back to the bottom. Three points! A triangle!

So anything outside of those boundaries is simply clipped out and do not appear. The element itself still maintains the footprint of it’s dimensions, however it’s presentational layer is changed.

Shapes

In the above example, we used a polygon to create a shape and defined a path by creating x and y pairs that were comma separated. However, we can work with different shapes that take differing values.

Circles

View the code on codepen

To create circles, we pass in three values to the circle shape. The x-axis and y-axis coordinates of the center of the circle, and the radius of the circle. When you define the radius of the circle, we use the keyword ‘at’ to define the x and y coordinates.

.clipClass {
-webkit-clip-path: circle(50% at 50% 50%);
}

Ellipses

View this code on codepen

Often you may not want a simple circle, but an oblong shape. Enter the ellipse shape.

With ellipsis, you provide four values, the x-axis and y-axis of the radius (or shape) of the ellipse, followed by the ‘at’ keyword that separates the x and y coordinates at which to position the ellipse.

.clipClass {
-webkit-clip-path: ellipse(30% 20% at 50% 50%);
}

Inset

(May be super buggy in older versions in of Chrome)

View the code on codepen

Perhaps you want to create rounded rectangles and the sharp edges of the polygon aren’t what you are searching for, enter the inset value. Inset takes four values that equate to Top, Right, Bottom, Left and allows a radius to be set for all four of those values.

.clipClass {
-webkit-clip-path: inset(25% 0 25% 0 round 0 25% 0 25%);
}

The above reads as

inset(<top> <right> <bottom> <left> round <top-radius> <right-radius> <bottom-radius> <left-radius>)

Whoa, confusing. Great news, there is a short hand version

.clipClass {
-webkit-clip-path: inset(25% 0 round 0 25%);
}

Quick Reference

Circle: circle(radius at x-axis y-axis)

Ellipse: ellipse(x-rad y-rad at x-axis y-axis)

Polygon: polygon(x-axis y-axis, x-axis y-axis, … )

Inset: inset(top right bottom left round top-radius right-radius bottom-radius left-radius)

Creating shapes

Seeing as the circle and radius shapes are limited by only a few values, Polygons are often the best choice for creating complex shapes. Having the ability to define multiple points helps to give us the ability to clip our elements in a variety of ways.

Comic Textbox

View the code on codepen

.clipClass {
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
}

Star

View the code on codepen

.clipClass {
-webkit-clip-path: polygon(50% 0%, 63% 38%, 100% 38%, 69% 59%, 82% 100%, 50% 75%, 18% 100%, 31% 59%, 0 38%, 37% 38%);
}

Animation

So now that we have a grasp on shapes and how to produce them, how about we use them to create effects.

We can have a shape applied on hover, and use a transition property to create a smooth effect, however we need to keep in mind that we have to create an initial default state with all the same coordinates that we are using in our hover state.

View the code on codepen

.animateClass {
-webkit-clip-path: polygon(20% 0%, 0% 0%, 0% 50%, 0% 80%, 0% 100%, 50% 100%, 80% 100%, 100% 100%, 100% 50%, 100% 0, 80% 0, 50% 0);
}
.animateClass:hover {
-webkit-clip-path: polygon(50% 0%, 0% 20%, 30% 50%, 0% 80%, 20% 100%, 50% 70%, 80% 100%, 100% 80%, 70% 50%, 100% 20%, 80% 0%, 50% 30%);
}

Using it in production

Being that support for clip-path shapes is limited to webkit browsers at the moment, there are obvious limitations when moving to Firefox and IE. Firefox does have other options such as SVG masking, but the transition between two states may not be possible on certain computers.

All in all, if you want to explore recreate certain effects though, Chrome and other webkit browsers, such as Safari are widely supported.

Back to the original task though

Since this all came up while attempting to recreate the effect of the Squarespace navigation. By utilizing positioning to overlay an element on another, and then using clip-path to the mask the image, we can now just simply show the background image without any fancy image replacement techniques.

View the code on codepen

I don’t know about you, but the future is looking more and more geometric.