How to create a triangle in CSS?
Create a CSS triangle with clip-path, the classic border trick or a linear gradient, with examples for every direction and tooltip arrows.
The easiest way to create a triangle in CSS is to give an element a size and a background, then cut it into shape with clip-path: polygon(). The three points of the polygon are the corners of the triangle.
.triangle {
width: 40px;
height: 30px;
background: #4f46e5;
clip-path: polygon(50% 0, 100% 100%, 0 100%);
}The points read as "top center, bottom right, bottom left", so this triangle points up. Each point is an x y pair measured from the top-left corner of the element.
This is the version I use. The triangle is sized with normal width and height, so it can be responsive, and the background can be a gradient or an image instead of a flat color.
Other directions with clip-path
Change the points, and keep everything else the same:
/* pointing down */
.triangle-down {
clip-path: polygon(0 0, 100% 0, 50% 100%);
}
/* pointing right */
.triangle-right {
clip-path: polygon(0 0, 100% 50%, 0 100%);
}
/* pointing left */
.triangle-left {
clip-path: polygon(100% 0, 100% 100%, 0 50%);
}For an equilateral triangle, the height is about 0.866 of the width, so width: 40px; aspect-ratio: 1 / 0.866 does the math for you.
One thing to know: clip-path also clips border and box-shadow. If you need a shadow, put filter: drop-shadow() on a parent element, because the parent's filter is applied after the child is clipped.
The classic border trick
Before clip-path, triangles were made with borders, and you'll still see this everywhere:
.triangle {
width: 0;
height: 0;
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-bottom: 30px solid #4f46e5;
}Why it works: where two borders meet, the browser joins them with a diagonal line. When the element has no width and no height, there is no content box between the borders, so each border becomes a triangle that points to the center. Make the side borders transparent and only the bottom one is visible. The result above is 40px wide and 30px tall.
The colored border decides the direction, and the triangle points away from it:
/* pointing down */
.triangle-down {
border-left: 20px solid transparent;
border-right: 20px solid transparent;
border-top: 30px solid #4f46e5;
}
/* pointing right */
.triangle-right {
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 30px solid #4f46e5;
}
/* pointing left */
.triangle-left {
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-right: 30px solid #4f46e5;
}The downsides: the size is set through border widths instead of width and height, and the fill can only be a solid color.
It's still common for tooltip and dropdown arrows, because a pseudo-element needs no extra markup:
.tooltip {
position: relative;
background: #1f2937;
}
.tooltip::after {
content: '';
position: absolute;
top: 100%;
left: 50%;
translate: -50% 0;
border: 8px solid transparent;
border-top-color: #1f2937;
}This puts a small arrow pointing down under the middle of the tooltip. For a complete tooltip, see how to create a tooltip in HTML and CSS.
Right-angled triangle with a gradient
For a right-angled triangle, you don't need to clip anything. A linear-gradient with a hard stop at 50% colors half of the box:
.corner {
width: 60px;
height: 60px;
background: linear-gradient(
to top right,
#4f46e5 50%,
transparent 50%
);
}With to top right, the 50% line runs exactly from the top-left corner to the bottom-right corner, whatever the size of the box. The colored half is the bottom-left one, so the right angle is in the bottom-left corner. This is handy for corner ribbons and diagonal section dividers, because it's just a background and can sit behind content.
Hard stops can look slightly jagged on a diagonal. If that bothers you, move the second stop by a fraction, for example transparent calc(50% + 0.5px).
Which one to use
Use clip-path. It's supported in all modern browsers, it's sized like any other element, and it works with gradients and images. Keep the border trick for existing code and small arrows on pseudo-elements, and reach for the gradient when you need a right-angled triangle as a background.
If a triangle carries meaning, like a sort direction or an "open" state, it's invisible to screen readers. Put that information in text as well, for example with aria-sort or aria-expanded on the related element.