If you want to create CSS Shapes, clip-path
is, without any doubt, the property you will need in most of the cases. In this article, I will share a few techniques I rely on when using the polygon()
value of clip-path
. Techniques that can make the process of creating CSS shapes easier.
I have wrote a lot of articles where I am creating different shapes using clip-path
that I invite you to read after this one. A good opportunity to practice the tricks we will study here.
- Triangle Shapes
- Polygon & Starburst
- Breadcrumb Navigation
- Ribbon Shapes
- Section Divider
- Tooltip Shapes
I also have an online collection of CSS Shapes where many of them are created using clip-path
.
Understanding The Coordinates
The first step is to understand the coordinates of the different points. To do this, the easiest way is to draw the four corner points like below:
The top-left corner is the origin with the (0,0)
coordinates and the bottom-right corner is the point having the (100%,100%)
coordinates. The X value grows from left to right and the Y value grows from top to bottom.
It’s very common to get lost within the coordinates if you don’t use polygon a lot. You may consider the origin to be the bottom-left or you get confused between the X and Y axis. To avoid making such mistakes, always draw the above figure on paper and start with the following polygon.
clip-path: polygon(0 0,100% 0,100% 100%,0 100%);
This polygon will simply draw a rectangle that fits the element boundaries so visually it will do nothing but it’s the starting point to draw CSS shapes. It may sound strange but that’s what I have been doing for years. I draw the coordinates on paper (now I can do it in my head), I start with that polygon then I am ready to draw the shapes.
Let’s try with two examples
The first shape on the left (the trapezoid) requires 4 points and our initial polygon already contains 4 points so we are not going to add new points. We will simply update the existing ones. Looking at the shape we can clearly see that we need to update the top-left and top-right corners. More precisely their X values.
clip-path:
polygon(
/* X Y */
0 0, /* --> 20% 0 */
100% 0, /* --> 80% 0 */
100% 100%,
0 100%
);
After identifying the points try to update the different values even with random ones to see how the polygon is changing. Once you are sure that you are updating the correct points, you can consider more precise values to get the final shape. It’s not easy to get the final shape from the first shot, there is always some trial & error. You will fail a lot trying to find which point to update and that’s fine. It’s part of the learning process.
Now that I know the points I have to update, I can define a variable to control my shape and change the code like below.
.trapezoid {
--s: 50px;
clip-path: polygon(var(--s)0,calc(100% - var(--s)) 0,100% 100%,0 100%);
}
For the second shape, we need to add more points. The number of points needs to be equal to 6 so we have to add 2 more points. Don’t pay attention to the coordinates of the new points. First, try to find their place within the initial polygon.
One point needs to be between the top-left and bottom-left corners and the other one between the top-right and bottom-right corners.
clip-path:
polygon(
/* X Y */
0 0, /* top-left */
100% 0, /* top-right */
X1 Y1,
100% 100%, /* bottom-right */
0 100%, /* bottom-left */
X2 Y2
);
Now, we can study and see how to update the different values. The new points are in the middle of the shape considering the Y-axis so their Y value will be equal to 50%
. One point is at the left and the other one at the right so let’s make their X value to be respectively 0
and 100%
.
clip-path:
polygon(
/* X Y */
0 0,
100% 0,
100% 50%,
100% 100%,
0 100%,
0 50%
);
At this step we have correctly placed our new points and their Y
values are correctly defined as well. Now, we need to update their X
values and also update the coordinates of other points. Can you figure out the changes we need to make? I let you continue this as a small exercise.
You may find such steps too long for a simple shape but they will help you simplify the process of creating shapes. If you are new to clip-path
and polygon()
, I highly recommend you take your time when you create CSS shapes. Don’t try to find all the points and their value at once. Update your polygon one value at a time and see the result. After a lot of practice, you will be able to skip most of the steps and draw complex shapes rapidly.
Analyze The Symmetry Of The Shape
Most of the CSS shapes we draw have some symmetry and this can help us calculate some values. If we take the previous example of the trapezoid, we have symmetry around a vertical axis that crosses the shape in the middle.
Considering this, we have two groups of points. The ones on the left and the ones on the right. I won’t start a boring geometry course but when we have such symmetry around the center, then each two points having the same Y value will have the sum of their X value equal to 100%
.
This means that you only need to know the values of half the points and then easily identify the remaining ones. It’s also a good way to debug the values you define.
Take the following polygon and try it
clip-path:
polygon(
/* X Y */
20% 0,
75% 0,
100% 100%,
0 100%
);
You won’t get a perfect trapezoid shape. The reason is that the X value of the top-left corner is equal to 20%
while the X value of the top-right corner is equal to 75%
. The sum is 95%
which is different from 100%
thus our shape is not symmetric. You have to change one of the values or both of them to get the correct result.
If you get back to my previous implementation, I am using var(--s)
and calc(100% - var(--s))
. The sum is always 100%
whatever the value of --s
.
Let’s take a more complex shape from a previous article
This ribbon shape requires a 14-point polygon which seems a lot. If you analyze its symmetry, you have the same thing as the trapezoid shape so you only have to focus on 7 points and easily find the others.
This trick is the most important one when working with clip-path
. Understanding the symmetry of the shape you want to create can reduce the effort by half and even more if you find more symmetry.
We can also have symmetry around the horizontal axis and when it’s the case, we consider the Y values instead of the X values. The sum of the Y values of two symmetric points needs to be equal to 100%
as well.
We can even have symmetry around both axes like the following starburst shape
We need 16 points to draw the shape and we have vertical and horizontal symmetry. We can split the different points into 4 groups and we only need to focus on one group which means only 4 points to find. Actually, only 3 points because we can remove one easy point that is placed above the axis of symmetry. It’s clear that finding 3 points is more easier than finding 16 points!
Try to draw this shape as a small homework to practice what we have learned so far. You don’t have to be accurate with the values. Try to define the points in a way to keep the symmetry of the shape even if the result is far from the original one.
Creating Different Variations From One Shape
Let’s take an example of a tooltip shape from my online collection:
Let’s suppose we have the clip-path
code of the above shape and we want to create the variations where the tail is at the top, the left, and the right.
Intuitively, you will redo the same process for each shape to get their code which means you need to do the same effort 4 times. It’s logical since the 4 shapes are different but we can avoid the extra work by using the code of one shape to get all the others. Another good trick that helps you get many shapes with less effort.
First, I am going to define 3 transformations that we can later apply to any shape we want.
Switching The Axes
The first transformation is to switch the X and Y values of each point. If you have the following polygon:
clip-path: polygon(x1 y1,x2 y2, ..., xn yn)
Change it to
clip-path: polygon(y1 x1,y2 x2, ..., yn xn)
Nothing complex and no need to find out why. Take it as a kind of automatic process. You will understand later what it does.
Inverting The X Values
For this transformation, we are going to update only the X values. Going from:
clip-path: polygon(x1 y1,x2 y2, ..., xn yn)
to
clip-path: polygon(calc(100% - x1) y1,calc(100% - x2) y2, ..., calc(100% - xn) yn)
Each X value is updated in a way to have both the old and new values symmetric around the vertical axis. Remember that the sum of symmetric points needs to be equal to 100%
, that’s why the formula is 100% - Xi
.
Inverting The Y Values
Same logic but this time with the Y values. Going from:
clip-path: polygon(x1 y1,x2 y2, ..., xn yn)
to
clip-path: polygon(x1 calc(100% - y1),x2 calc(100% - y2), ..., xn calc(100% - yn))
Now if you apply one of these transformations to an existing shape you get another variation with 0 effort. You may ask which one to use, right? The answer is: “Try and see!” You can better understand this technique by applying it to real examples.
Take the code of the first tooltip shape from my online generator and try to get the other variations. Here is a figure to illustrate the transformations that convert one shape to another.
And here is another example using ribbon shapes from my other collection.
If you have the code of one shape, you can easily find the code of more variations. That’s how I was able to easily create a collection of more than 100 different shapes. In the end, I made the effort to create around 20 or 30 shapes and all the others are variations.
Using Developer Tools
I will end this article by showing you how to use Developer tools to easily modify the coordinates of your points using drag & drop. You can find a lot of online tools to do this but there is a built-in one provided by Firefox that helps you work directly on your code. Simple but yet effective!
If you inspect the code of your element, you can find a small icon next to the polygon. If you click on it, the points will appear on the screen and you can drag them with your mouse to update the values.
It doesn’t work with complex shapes where you have calc()
or CSS variables but still a good tool for basic shapes if you want to easily visualize the different points and update them in real time. If you make some changes, don’t forget to copy the code before refreshing your browser!
Conclusion
Now it’s your turn to start creating CSS Shapes. I focused on the tricks and the theory part but nothing beats practice. Even if what I explained sounds easy, the only way to understand it well is to apply it to real examples.
I will share again my previous articles where I am exploring CSS shapes made with clip-path
. consider them as a follow-up to this article to get better at creating shapes or to get some inspiration.
- Triangle Shapes
- Polygon & Starburst
- Breadcrumb Navigation
- Ribbon Shapes
- Section Divider
- Tooltip Shapes
Don't forget to bookmark my CSS Shapes collection if need to easily get the code of any shape.
Temani Afif is an expert web developer, a content creator, and a CSS addict. He is the mastermind behind CSS Loaders, CSS Generators, CSS Tip and a lot of CSS stuff.
View all posts by Temani Afif