How to Use CSS Shapes in Your Web Design

The layout principles–columns and rows, angles and lines–that we use to build websites today are largely influenced by their print heritage. And although grid implementation on the web is getting better and more polished, web layout in general is still awkward compared to print media, especially when it comes to content flow.
Magazines and newspapers have always enjoyed elegant ways for arranging content layout, such as wrapping text around, or inside, non-rectangular shapes.



Let’s explore how the CSS Shapes Module will allow us this same freedom on the web.
Quick Intro to CSS Shapes
CSS Shapes enable web designers to create more abstract, geometric layouts, beyond simple rectangles and squares. The specification provides us with new CSS properties which include shape-outside
and shape-margin
. Browser support is reasonable, though these properties are currently only available in Chrome, Opera, and Safari, with the -webkit-
prefix, hence -webkit-shape-outside
.
The shape-outside
property will cause inline content to wrap around (outside) following the element curve, rather than the box model. Initially there was also shape-inside
to wrap the content inside an element; text within a circular element would be moulded into a circle shape as well. However, the implementation has been postponed for CSS Shapes Level 2.



The shape-margin
property sets the margin around whichever shape is using the shape-outside
.
Let’s take a look at some examples.
Creating a Shape
The easiest way to find out how CSS Shapes works is probably through creating a circle. So, here’s a div
(our circle), with several paragraphs alongside.
1 |
<div class="circle"></div> |
2 |
<p>Lorem ipsum…</p> |
3 |
<p>Lorem ipsum…</p> |
4 |
<p>Lorem ipsum…</p> |
Here’s some basic styling, including the width and the height of our circle, the border-radius
to shape the element, and a float so the paragraph wraps around the element.
1 |
.circle { |
2 |
width: 250px; |
3 |
height: 250px; |
4 |
background-color: #40a977; |
5 |
border-radius: 50%; |
6 |
float: left; |
7 |
}
|
As the we would except, the paragraphs is now wrapped around the element. However, since the border-radius property does not define the actual element shape, the paragraph wrap does not form the circle curve.
If we inspect the element through our browser DevTools, we will find the element is, in fact, still a box. So, even though our div has the appearance of a circle, the border-radius
has done nothing to the actual shape of the element.



In order for our paragraph to adhere to the circular shape, we need to change the actual element shape through the shape-outside
property; in this case, we’ll add one with the circle()
function passed as the value.
1 |
.circle { |
2 |
width: 250px; |
3 |
height: 250px; |
4 |
background-color: #40a977; |
5 |
border-radius: 50%; |
6 |
float: left; |
7 |
-webkit-shape-outside: circle(); |
8 |
shape-outside: circle(); |
9 |
}
|
Our paragraphs now wrap neatly around the circle’s circumference.
Additionally, if we now inspect the element through DevTools, we’ll see that the element is properly rendered into a circle.



With some margins, look how it might enhance a simple layout:
Customizing the Circle
The circle()
function takes a couple of values for defining the radius and the center coordinate respectively: circle(r at x y)
. By default, the radius value is derived from the element size; if the element is 300px
wide, for instance, the radius will be 150px
(the radius being half of the circle’s diameter).
Similarly, the x
and y
coordinates are measured relative to the element’s size, and they are by default set at 50% 50%
; right at the centre of the element.



These two values will come in useful when you want to resize the shape, while keeping the actual element size, or move the shape while retaining the element position. In the following example, we’ll reduce the circle radius down to 60px
and set the center coordinate to 30% 70%
, which should move the circle to the bottom left of the element box.



It is worth noting that when modifying the circle both the center coordinate and the radius have to be explicitly defined; adding only one of the them is invalid.
1 |
circle( 60px at 30% 70% ) // correct. |
2 |
circle( 60px ) // invalid. |
3 |
circle( at 30% 70% ) // invalid. |
Shape Box Model
CSS Shapes inherit the same box model principle as the element, but applied outside the scope of the element itself. This allows us to separately set the element, say, to border-box
while setting the shape to padding-box
. To change the shape box model, add one of the box model keywords, content-box
, margin-box
, border-box
, or padding-box
after the function.
1 |
.circle { |
2 |
width: 250px; |
3 |
height: 250px; |
4 |
background-color: #40a977; |
5 |
border-radius: 50%; |
6 |
float: left; |
7 |
padding: 10px; |
8 |
border: 20px solid #ccc; |
9 |
margin: 30px; |
10 |
-webkit-shape-outside: circle() padding-box; |
11 |
shape-outside: circle() padding-box; |
12 |
}
|
The default box-model of the shape is set to margin-box
. And in the following example, we’ve changed it to padding-box
to tell the browser to exclude the element margin when determining the shape size or span. Now we should find the paragraph pass through the border, and immediately touching the padding of the element.



I highly recommend checking out our free course on the Basics of CSS Box Model for more about how the box-model works in detail.
Creating More Shapes
The CSS Shapes specification comes with a few more shape functions:
-
ellipse()
: As the name implies, this function will create an ellipse shape. We can configure the ellipse radius and move the shape center coordinate as well. But unlike thecircle()
function, theellipse()
function applies two radius measurements, horizontal and vertical, henceellipse( 100px 180px at 10% 20% )
. -
polygon()
: This function enables us to create more complex shapes like triangles, hexagons, as well as non-geometrical shapes. Using polygon is not as easy as creating a circle, but the Path to Polygon Converter tool makes it a bit more intuitive.
Wrapping Up
In this tutorial, we looked into the basic application of CSS Shapes; we created a shape, customized the size, the position, and the box model. At the time of the writing, several aspects of CSS Shapes are still very rough around the edges, which is probably why we don’t see it used widely just yet.
- As mentioned earlier in this tutorial, the CSS Shapes
shape-inside
property, which allows us to wrap and shape content inside an element, has been put on ice. - The CSS Shapes specification provides a separate property named
shape-box
to define the shape box-model, though it currently seems inapplicable to any browsers. - Safari requires the
-webkit-
prefix, highlighting that this feature is experimental.
Nonetheless, despite slow progress and disparity across browsers at the moment, I’m looking forward to CSS Shapes! Once the major browsers pick it up I can’t wait to see some really creative layouts on the web!