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.

Multipurpose Magazine by GreenSocks

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.

From top to bottom: shape-outside and shape-inside in action.

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.

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.

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.

Notice the rectangular highlight around 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.

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.

Notice the darker highlight.

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.

The circle is positioned at the center 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.

The paragraphs now pass through the element box following the circle size. View the demo.

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.

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.

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.

The orange square is the margin, the yellow square is the border, and the green square is the padding,

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 the circle() function, the ellipse() function applies two radius measurements, horizontal and vertical, hence ellipse( 100px 180px at 10% 20% ) .

: 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 the function, the function applies two radius measurements, horizontal and vertical, hence . 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.

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.

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!