CSS Reference Data Type

<basic-shape>

The <basic-shape> CSS value represents, as the name suggests, a basic shape that is defined using a shape function. A basic shape can then be passed as a value to a property such as the shape-outside property, or the clip-path property, which are used to apply the shape to an element in order to change the flow of content around it, or to clip the element to the defined shape, respectively.

basic-shape-example
The four vertices in this screenshot represent the vertices of a basic polygonal shape defined on the image. The shape is used to clip the image to the shape using the clip-path property, and the same shape is also used as a value for the shape-outside property, in order to change the flow of content around the image to accommodate the defined shape.

Refer to the entries of the shape-outside property and the clip-path property for more information.

Screenshot is taken from this article explaining the use of the shape in detail.

The <basic-shape> type can be specified using basic shape functions. See the Values section below for a list of possible shape function values and their description.

A shape’s reference box

In addition to the element’s height and width, the element’s box model boxes—margin box, content box, padding box, and border-box—are also used as a reference to specify the extent of the shape on an element. The reference box can be any of the four boxes.

When a <basic-shape> is used to define shapes, the reference box is defined by each property that uses <basic-shape> values (see the Examples section below). The coordinate system for the shape has its origin on the top-left corner of the reference box with the x-axis running to the right and the y-axis running downwards. All the lengths expressed in percentages are resolved from the used dimensions of the reference box. If no reference box is specified, the border-box will be used as reference box for the clip-path property, and the margin-box is used for shapes used in the shape-outside property.

Trivia & Notes

It is possible that in the future more CSS properties will take a <basic-shape> as a value (for example, the upcoming shape-inside from the second level of the CSS Shapes Module), so this value is not exclusive to the above two properties.

Values

inset()
inset() = inset( [offset]{1,4} [round <border-radius>]? )
/* where.. */
offset = <length> | <percentage>
                        

The inset() functions defines an inset rectangle. It takes one to four offset values, which specify the offsets from the edges of the references box inward. These specify where the inset rectangle goes inside the element.

The syntax of the offsets is the same as the syntax of the margin shorthand property. This means that you can set all four insets with one, two or four values. If one offset value is specified (e.g 15px), it will be used as a top, right, bottom, and left offset. If two offset values are specified (e.g 20px 10px), they specify the top and bottom offsets and the right and left offsets, respectively. If three values are specified (e.g 10px 15px 20px), the first specifies the top offset, the second specifies the right and left offsets, and the third specifies the bottom offset. If four values are specified, the first is used as the top offset, the second as the right offset, the third as the bottom offset, and the fourth as the left offset.

And just like with margins, the offset values can be set in absolute lengths or percentages.

In addition to the offset value(s), the inset() function takes an optional border-radius value that specifies the amount by which the corners of the rectangles are to be rounded. The border-radius argument uses the same syntax as the syntax of the border-radius property—one to eight values specifying the rounding value for the four corners in either or both horizontal and vertical dimensions. Refer to the border-radius property entry for more information about it if you’re not already familiar with it. The border radius specified must be preceded by the round keyword.

The following are all valid inset() rectangle shape declarations:

inset(10% 20% round 5px); 
/* a rectangle with 5px rounded corners, whose edges 
are set inwards by 10% from the top and bottom edges 
of the reference box, and 20% inwards from the left 
and right edges of the box */

inset(15px 20px 30px); 
/* creates a non-rounded inset rectangle, set inwards 
by 15px from the top, 20px from the right and left 
edges of the reference box, and 30px inwards from the 
bottom edge of the reference box */

inset(25% round 10px 30px);
/* creates a rectangle set inwards by 25% in all four
directions relative to the edges of the reference box, 
and has top-left and bottom-right corners rounded by 
10px, and the top-right and bottom-left corners 
rounded by 30px */

inset(10px 20px 30px 40px round 10px);
                        
circle()
circle() = circle( [<shape-radius>]? [at <position>]? )
/* where.. */
<shape-radius> = <length> | <percentage> | closest-side | farthest-side
                        

The circle() function is used to define a circle. The question marks indicate that both parameters are optional and can be omitted. If you omit one, that parameter is set to its default value by the browser.

If you omit the position argument, the center of the circle will be positioned at the center of the element it is used on. You can specify a position using the same syntax as that of the background-position property syntax. The position is preceded by the at word.

The shape-radius parameter specifies the radius of the circle. It can be set in absolute lengths or percentages. A percentage value here is resolved from the used width and height of the reference box. Negative values are not allowed.

In addition to using lengths and percentages to specify the circle’s radius, it can also be set using one of two keywords: closest-side or furthest-side. closest-side is the default value, which means that, if you omit this argument and don’t specify a radius for the circle, the browser will use the length from the center of the element to its closest side in any dimension as the length of the radius. farthest-side uses the length from the center to the farthest side.

The following illustration explains the closest-side and farthest-side radius values visually.

closest-side-farthest-side

The following are all valid circle() shape declarations:

circle(); 
/* use default values: circle with closest-side radius, 
positioned at the center of the element */

circle(100px at 30% 50%); 
/* circle of radius 100px positioned at 30% horizontally 
and 50% vertically */

circle(farthest-side at 25% 25%); 
/* defines a circle whose radius is half the length of 
the longest side, positioned at the point of 
coordinates 25% 25% on the element’s coordinate system */

circle(10em at 500px 300px); 
/* defines a circle whose center is positioned at 500px 
horizontally and 300px vertically, with a radius of 
10em */
                        
ellipse()
ellipse() = ellipse( [<shape-radius>{2}]? [at <position>]? )
/* where.. */
<shape-radius> = <length> | <percentage> | closest-side | farthest-side
                        

The ellipse() function defines an ellipse shape. It takes the same arguments list and values as the circle() function, except that instead of taking one shape radius value, it takes two radii, rx and ry, that represent the x-axis and y-axis radii of the ellipse, in that order. Also, percentage values here are resolved against the used width (for the rx value) and the used height (for the ry value) of the reference box.

See the circle() function description above for more information about the possible arguments, their meanings, and possible values.

Note about closest-side: For circles, this is the closest side in any dimension. For ellipses, this is the closest side in the radius dimension.

Note about farthest-side: For circles, this is the farthest side in any dimension. For ellipses, this is the farthest side in the radius dimension.

The following are all valid ellipse() shape declarations:

ellipse(); 
/* use default values */

ellipse(100px 50px at 30% 50%); 
/* ellipse of x-radius 100px and y-radius 50px 
positioned at 30% horizontally and 50% vertically */

ellipse(farthest-side closest-side at 25% 25%); 
/* defines an ellipse whose x-radius is half the length 
of the longest side, and whose y-radius is half the length 
of the shorter side, positioned at the point of 
coordinates 25% 25% on the element’s coordinate system*/

ellipse(10em 10em at 500px 300px); 
/* defines a ellipse whose center is positioned at 500px 
horizontally and 300px vertically, with both x and y 
radii of 10em (this is basically a circle) */
                        
polygon()
polygon() = polygon( [<fill-rule>,]? [<shape-arg> <shape-arg>]# )
/* where.. */
<shape-arg> = <length> | <percentage>
                        

The polygon() function is used to define more complex arbitrary shapes using any number of points. The function takes in a set of coordinate pairs (<shape-arg> <shape-arg>), each pair specifying the position of a point. The first argument represents the x-position of a point, and the second argument represents the y-position. The set of points make up the shape. The browser will connect the last vertex in the list with the first vertex in the list to close the polygon, so you don’t have to do that yourself. Coordinate pairs are comma-separated, and can be set using either absolute lengths or percentages.

In addition to the set of coordinate pairs, the polygon() function can take an optional argument called the fill-rule. This specifies how to treat areas inside the polygonal shape that may intersect itself. See fill-rule property in SVG for details. Possible values are nonzero or evenodd. Default value when omitted is nonzero.

The following are all valid polygon() function declarations:

polygon(0 0, 100% 100%, 0 100%);

polygon(0 0, 100% 100%, 0 100%);

polygon(50px 0px, 100px 100px, 0px 100px);

polygon(170.67px 291.00px, 126.23px 347.56px, 139.79px 417.11px, 208.92px 466.22px, 302.50px 482.97px, 343.67px 474.47px, 446.33px 452.00px, 443.63px 246.82px, 389.92px 245.63px, 336.50px 235.26px, 299.67px 196.53px, 259.33px 209.53px, 217.00px 254.76px);

polygon(evenodd, 446.33px 452.00px, 443.63px 246.82px, 389.92px 245.63px, ...);
                        

Notes

The values in a basic shape function are computed as specified, with these exceptions:

  • Omitted values are included and compute to their defaults.
  • A <position> value in circle() or ellipse() is computed as a pair of offsets (horizontal then vertical) from the top left origin, each given as a combination of an absolute length and a percentage.
  • A <border-radius> value in inset() is computed as an expanded list of all eight <length> or percentage values.

The reference box for the shapes is defined as part of the property that takes these shapes as values. See the Examples section next for examples.

Interpolation of Basic Shapes (Animating between Shapes)

For interpolating between one basic shape and a second, the rules below are applied. The values in the shape functions interpolate as a simple list. The list values interpolate as length, percentage, or calc where possible. If list values are not one of those types but are identical (such as finding nonzero in the same list position in both lists) those values do interpolate.

  • Both shapes must use the same reference box.
  • If both shapes are the same type, that type is ellipse() or circle(), and none of the radii use the closest-side or farthest-side keywords, interpolate between each value in the shape functions.
  • If both shapes are of type inset(), interpolate between each value in the shape functions.
  • If both shapes are of type polygon(), both polygons have the same number of vertices, and use the same <fill-rule>, interpolate between each value in the shape functions.
  • In all other cases no interpolation is specified.

Examples

The following example defines a shape used to change the shape of the float area of an element using the shape-outside property. Notice how the reference box of the shape is defined inside the property’s declaration.

.element {
    shape-outside: circle(100px at 50% 50%) margin-box;
}
                

The result of the above code would look similar to the following image. Refer to the shape-outside property entry for more examples on using basic shapes to change the flow of content around elements.

circle-shape

The following example defines a polygonal shape used with the clip-path property to clip an element to the defined shape:

.element {
    clip-path: polygon(26px 111px, 222px 386px, 311px 281px, 470px 393px, 660px 293px, 604px 47px, 505px 107px, 318px 37px, 42px 107px);
}
                

See the live demo below for a live example.

Live Demo

The following demo uses the clip-path property to clip an element to the shape defined as the property’s value. The shape defined is a random polygonal shape using the polygon() function.

Try changing the shape function and playing with the values to see how the element’s shape changes accordingly. Note that the demo currently only works in Webkit-based browsers, so you need to use an appropriate browser to view a working demo and be able to experiment with the values.

View this demo on the Codrops Playground

Browser Support

Please refer to the browser support section for the shape-outside property.

Written by

Last updated March 6, 2020 at 3:33 am by Mary Lou

Do you have a suggestion, question or want to contribute? Submit an issue.