Basic shapes with shape-outside
CSS shapes can be defined using the<basic-shape>
type. In this guide, we discuss creating rectangles, circles, ellipses, and polygons with theshape-outside
property. These are features defined in theCSS shapes module.
Before looking at shapes, it is worth understanding two pieces of information that go together to make these shapes possible:
- The
<basic-shape>
type - The reference box
In this article
The <basic-shape> type
The<basic-shape>
type is used as the value for all of our basic shapes. This type is a functional notation: the function parentheses contain arguments used to describe the shape.
The accepted arguments vary depending on the shape you are creating. We will cover these in the examples below.
The reference box
Understanding the reference box used by CSS shapes is important when using basic shapes, as it defines each shape's coordinate system. You have already met the reference box inthe guide on creating shapes from box values, which directly uses the reference box to create the shape.
The screenshot below shows the Firefox Shapes Inspector displaying the reference box of a circle created usingshape-outside: circle(50%)
. The element has 20 pixels of padding, border, and margin applied. The Shapes Inspector highlights these reference boxes.
The default reference box for a basic shape is themargin-box
. You can see in the screenshot that the shape is defined relative to that part of the Box Model.
While the default reference box ismargin-box
, this can be modified. To set a different box as the reference box, include the desired box value after your basic shape definition.
These two declarations are the same:
shape-outside: circle(50%);shape-outside: circle(50%) margin-box;
For your shape to use a different reference box, include a different<box-edge>
value, for example, to use the border as a reference box for our circle, set:
.shape { shape-outside: circle(50%) border-box;}
Shapes created that extend past the margin box will have the shape clipped to the margin box. The following basic shapes demonstrate this.
inset()
Theinset()
function defines a rectangle. This may not seem very useful as floating an item, without shapes, will give you a rectangular shape around it. However, theinset()
type enables the definition of offsets, thus pulling the wrapping text around the reduced-size rectangle, over parts of the floated element.
Theinset()
function takes up to four side offset values, plus an optionalround
keyword, followed by aborder-radius
value. The below CSS creates a rectangular shape inset from the reference box of the floated element 20 pixels from the top and bottom and 10 pixels from the left and right, with aborder-radius
value of 10 pixels.
.shape { float: left; shape-outside: inset(20px 10px 20px 10px round 10px);}
The offset values use the same rules as themargin
shorthand. Four space-separated values define the top, right, bottom, and left offsets — in that order. You can also set more than one offset at once:
- If there is only one value, it applies to all sides.
- If there are two values, the top and bottom offsets are set to the first value and the right and left offsets are set to the second.
- If there are three values, the top is set to the first value, the left and right are set to the second, and the bottom is set to the third.
The above rules can therefore also be written as:
.shape { float: left; shape-outside: inset(20px 10px round 10px);}
In the example below we have aninset()
shape used to pull content over the floated element. Change the offset values to see how the shape changes.
<div> <div></div> <p> One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery. Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact. </p></div>
body { font: 1.2em sans-serif;}.shape { float: left; width: 150px; height: 100px; shape-outside: inset(20px 50px 10px 0 round 50px); background-color: rebeccapurple; border: 2px solid black; border-radius: 10px; margin: 20px; padding: 20px;}
You can also add a box value as an alternative reference box. In the example below, try changing the reference box frommargin-box
toborder-box
,padding-box
, orcontent-box
to see how the reference box used as the starting point changes before offsets are calculated.
<div> <div></div> <p> One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery. Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact. </p></div>
body { font: 1.2em sans-serif;}.shape { float: left; width: 150px; height: 100px; shape-outside: inset(20px 50px 10px 0 round 50px) margin-box; background-color: rebeccapurple; border: 2px solid black; border-radius: 10px; margin: 20px; padding: 20px;}
You can also create rectangles based on distances from the top and left edges of the reference box with therect()
function, or by width and height with thexywh()
function; both of these also support optional rounded corners.
circle()
Thecircle()
value forshape-outside
can accept two possible arguments: a<shape-radius>
defining the size and the<position>
defining its location.
Thecircle()
andellipse()
shape-outside
values both accept<shape-radius>
as an argument. This can be a<length>
, a<percentage>
, or one of the keywordsclosest-side
orfarthest-side
.
Theclosest-side
keyword value uses the length from the center of the shape to the closest side of the reference box to create the radius length. Thefarthest-side
keyword value uses the length from the center of the shape to the farthest side of the reference box.
The second argument is aposition
, which accepts a one- or two-keyword<position>
value, to indicate the position of the center of the circle. This is specified the same way asbackground-position
; if one or both values are omitted, the values default tocenter
.
To create a circle, we include a single radius value, optionally followed by the keywordat followed by a position value. This example has a circle applied to an<img>
with awidth
andheight
of210px
and amargin
of20px
. This gives a total width for the reference box of250px
. The50%
value for the<shape-radius>
means the radius is125px
. The position value is set to30%
, which is30%
from the left and at the default verticalcenter
.
<div> <img alt="An orange hot air balloon as seen from below" src="https://mdn.github.io/shared-assets/images/examples/round-balloon.png" /> <p> One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery. Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact. </p></div>
body { font: 1.2em sans-serif;}img { float: left; shape-outside: circle(50% at 30%); margin: 20px;}
Play with increasing or decreasing the size of the circle by changing the size of the radius, moving the circle around with the position value, or setting a reference box as we did forinset()
.
The below example combines generated content with acircle()
function that uses the keywordstop left
for position. This creates a quarter circle shape in the top left corner of the page for text to flow around.
<div> <p> One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery. Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact. </p></div>
body { font: 1.2em sans-serif;}.box::before { content: ""; float: left; width: 250px; height: 250px; shape-outside: circle(50% at top left);}
The shape will be clipped by the margin box
As noted inreference boxes above, themargin-box
will clip the shape. You can see this by moving the center of our circle towards the content by setting the position to60%
. The center of the circle will be nearer to the content and the circle will extend past the margin-box. This means that the extension becomes clipped and squared off.
img { float: left; shape-outside: circle(50% at 60%);}
ellipse()
An ellipse is a squashed circle. As such, theellipse()
function acts in a very similar way tocircle()
except that we have to specify two radii,x
andy
, in that order.
These may then be followed by one or two<position>
values, as withcircle()
, to define the location of the center of the ellipse. In the example below, we have an ellipse with anx
radius of40%
, ay
radius of50%
and the<position>
set toleft
. This means that the center of the ellipse is at the center of the left edge of the reference box. This creates a half ellipse shape around which the text will wrap. You can change these values to see how the ellipse changes.
<div> <div></div> <p> One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery. Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact. </p></div>
body { font: 1.2em sans-serif;}.shape { float: left; shape-outside: ellipse(40% 50% at left); margin: 20px; width: 100px; height: 200px;}
The keyword values ofclosest-side
andfarthest-side
are useful in creating a quick ellipse based on the size of the floated element reference box.
<div> <div></div> <p> One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery. Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact. </p></div>
body { font: 1.2em sans-serif;}.shape { float: left; shape-outside: ellipse(closest-side farthest-side at 30%); margin: 20px; width: 100px; height: 140px;}
polygon()
Thepolygon()
function is more complex, enabling the creation of multiple-sided polygon shapes. This shape accepts three or more pairs of values (a polygon must at least draw a triangle). Each space-separated pair of values is separated with a comma and represents the coordinates of a single vertex drawn relative to the reference box. Each pair of coordinates defines an edge of the polygon, with the final edge defined by the first and last set of coordinates.
The example below creates a shape for text to follow using thepolygon()
function. Try changing the coordinate values to see how the shape changes.
<div> <div></div> <p> One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery. Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact. </p></div>
body { font: 1.2em sans-serif;}.shape { float: left; shape-outside: polygon( 0px 0px, 0px 189px, 100.48% 94.71%, 200px 120px, 80.67% 37.17% ); width: 200px; height: 200px;}
To create even more complex shapes, you can define the outline of any shape with thepath()
orshape()
functions.
Theinset()
,circle()
,ellipse()
, andpolygon()
are inspectable and editable using the Firefox Developer Tools Shape Inspector. The screenshot below shows the shape highlighted in the tool.
Another resource isClippy, a tool for creating shapes with examples using the CSSclip-path
property, which uses the same basic shape functions and values as theshape-outside
property.