polygon()

John Rhea on

Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.

The CSS polygon() function allows you to create any type of polygon to use in the shape-outside, clip-path, and offset-path properties.

.polygonous {
  width: 500px;
  height: 500px;
  background-color: firebrick;
  /* generates a dodecagon */
  clip-path: polygon(50% 0%, 75% 6.7%, 93.3% 25%, 100% 50%, 93.3% 75%, 75% 93.3%, 50% 100%, 25% 93.3%, 6.7% 75%, 0% 50%, 6.7% 25%, 25% 6.7%);
}

“Drawing” Shapes

As with the other functions that produce a basic shape — including circle(), ellipse(), inset(), xywh(), path() and shape() — you won’t be drawing shapes directly on the screen in the way you’d normally think. You will either be creating a shape for text and elements to flow around (shape-outside), creating a cookie cutter to cut the shape out of another element (clip-path), or creating a shape that another element could move along (offset-path).

Clarification note: Neither path() nor shape() can be used with the shape-outside property like the other basic shape functions.

Reference Box

Before we get too deep, let’s discuss the reference box. This is the box upon which the basic shapes used in shape-outside and clip-path is formulated.

By default, the box defined by the outer edges of the margins is the reference box, so a shape must fit inside the reference box to have an effect. If the shape is larger than the reference box, then the outer edges of the element will remain intact, i.e. its unmodified rectangular form.

For the shape-outside property, this means the text and elements will flow around the element as if no shape-outside property was used. For clip-path, it similarly means that nothing will be clipped because the entire element fits within the cookie cutter. If you need to change the reference box, you’ll need to add the appropriate keyword (margin-box, padding-box, border-box, etc.) to clip-path or shape-outside.

The offset-path property is not limited by the reference box in the same way shape-outside and clip-path are limited by it. An offset-path whose shape is well outside the reference box will still allow an element to move along it, however, the reference box used can affect where and how the shape is “drawn.”

Basic Usage

Let’s start with clip-path so that we can more easily see the size and edges of the polygons we create.

.polygonous {
  width: 500px;
  height: 500px;
  background-color: firebrick;
  /* generates a five pointed star */
  clip-path: polygon(10% 40%, 40% 40%, 50% 10%, 60% 40%, 90% 40%, 65% 60%, 75% 90%, 50% 70%, 25% 90%, 35% 60%); 
}

Next, let’s use shape-outside to flow some text along some starry sides. Notice that you can only see the right side of the star because the text only flows around the right side of the shape.

.polygonous {
  width: 300px;
  height: 300px;
  background-color: firebrick;
  /* generates a five pointed star */
  shape-outside: polygon(10% 40%, 40% 40%, 50% 10%, 60% 40%, 90% 40%, 65% 60%, 75% 90%, 50% 70%, 25% 90%, 35% 60%);
  float: left;
}

Finally, let’s animate our star around a star using offset-path:

.polygonous {
  width: 300px;
  height: 300px;
  background-color: firebrick;
  /* Cuts the polygon/star out of the element */
  clip-path: polygon(10% 40%, 40% 40%, 50% 10%, 60% 40%, 90% 40%, 65% 60%, 75% 90%, 50% 70%, 25% 90%, 35% 60%);
  /* Defines the animated path */
  offset-path: polygon(10% 40%, 40% 40%, 50% 10%, 60% 40%, 90% 40%, 65% 60%, 75% 90%, 50% 70%, 25% 90%, 35% 60%);
  offset-distance: 0;
  /* Applies the animation */
  animation: star-offset 5s linear infinite;
}

/* Defines the animation */
@keyframes star-offset {
  from {
    offset-distance: 0;
  }
  to {
    offset-distance: 100%;
  }
}

Syntax

<polygon()> = polygon(
  <'fill-rule'>? 
  [ round <length> ]? ,
  [<length-percentage> <length-percentage>]#
)

In plain English, this means that the polygon() function accepts two parameters: a fill rule and the X and Y coordinates of the shape in length units.

Parameters

The polygon() function takes an optional keyword — the fill rule — and a set of points, i.e., the polygon’s vertices.

Fill Rule

The first keyword in the polygon() function (which was omitted from the above examples because it’s optional) is the fill rule. This tells the browser how to fill the shape with color. There are two options: nonzero and evenodd (the same as in SVG). In most shapes, they work the same, however, when a polygon overlaps itself, the algorithms differ on what they fill with color and what they don’t.

The algorithm descriptions below are included for completeness. You don’t need to understand how the algorithms work to use polygon(). Most of the time you can use the default value (nonzero) and it will work the way you’d expect. If it ever isn’t working the way you want, try switching to evenodd. And if that doesn’t work, then the fill rule isn’t the issue.

  • nonzero (default): The browser picks a point and draws a ray (a straight line) out of the shape. The browser also sets a direction along the shape’s path (basically, if it were being drawn, it chooses a direction the pen is moving in to complete the shape). It doesn’t really matter where it starts or which direction it begins in because the algorithm only cares about the ray crossing paths that move (or are drawn in) opposite directions. When the ray crosses part of the shape’s path, the browser increments or decrements a counter. If the ray crosses a part of the path moving in a clockwise direction, the browser increments; if the path is moving counterclockwise, the browser decrements. When the resulting counter is not zero, the point is inside the shape and within the fill. If the counter is zero, the point is outside.
  • evenodd: The browser picks a point and draws a ray (a straight line) from that point out of the shape (it does not care about the direction of the shape’s path). Every time the ray crosses a path of the shape it increments a counter. If the counter ends as an odd number, the point is considered inside the shape and within the fill. If the counter is even, the point is outside the shape.

If a fill rule is used it should be followed by a comma (,).

Points

The set of points is a comma separated list of space separated X and Y coordinates.

polygon(10% 40%, 40% 40%, 50% 10%, 60% 40%, 90% 40%, 65% 60%, 75% 90%, 50% 70%, 25% 90%, 35% 60%)

There must be at least three points (I see you there, Mr. Triangle), but there’s no upper limit on the number of points so whether enneacontagon (90 sides) or hectotetracontagon (140 sides) fit your fancy you can create them with polygon().

Points will be connected from the first point to the next all the way through with the last point automatically connecting back to the first. Thus the order the points are in will determine the final shape. If you mix up the order of the points you could have a very, very different shape than what you started with.

You cannot have open line segments with polygon(). It has to be a closed shape (it has to be a polygon after all), but there’s no requirement that the polygon doesn’t twist and turn over itself (hence the need for the fill rule earlier).

You can create shapes that appear to be separate by repeating points (sort of running two edges of the cookie cutter so close that they virtually disappear). In the next demo, the bottom-right point of the upper star is followed by the left-most point of the lower star. The lower star’s points are then all listed, finishing with a repeat of the left-most-point of the lower star. We then repeat the bottom right point of the upper star and finish out the rest of the upper star. (The “Widen Connecting Point” button below simply offsets the repeated points by half a percent to show the connective tissue.)

You can even recreate the wild imaginings of Lewis Carroll like in his poem, The Mouse’s Tale:

You can even animate from one polygon to another, though for best results animate between two polygons with the same number of points. The browser doesn’t require them to be the same number of points, but the tweening can get wild when it tries to go from a single point to two or more.

Browser Support

Specification

The CSS polygon() function is defined in the CSS Shapes Module Level 1 specification, which became a Candidate Recommendation on June 12, 2025. That means it integrates changes from a previous Candidate Recommendation (Draft or Snapshot) to allow for review and for ease of reference to the integrated specification, but those changes have not undergone a formal review.