Shapes in CSS: Freeing the layout

Shapes allow you to wrap text around parts of an image or a predefined shape. Using these shapes we can change the way text looks on the screen

Shape without image

In its most simple way, we can wrap text around an invisible shape defined as we would a clip-path.

The HTML defines an empty div element that will hold the shape we define in CSS.

<div class="coffee"></div>
<p>Dark, lungo, café au lait in latte fair
trade blue mountain strong, redeye sugar
seasonal café au lait Turkish. Black mug
variety, cappuccino, single-shot body sit
grounds coffee whipped Turkish et, skinny,
doppio so filter Turkish spoon affogato rich.

The CSS for the .cofee div we defined in markup holds the shape that the text will flow around.

The element must have explicit dimensions (width and height) and must be floated.

The shape-outside attribute describes the shape that the text will wrap around.

.coffee {
  shape-outside: circle(40%);
  float: left;
  height: 300px;
  width: 300px;
}

The examples, so far have only used a single shape, but you can use other values for shape-outside as shown in the list below, taken from (MDN).

none
The float area is unaffected. Inline content wraps around the element’s margin box, like usual.
<shape-box>
The float area is computed according to the shape of a float element’s edges (as defined by the CSS box model). This can be margin-box, border-box, padding-box, or content-box. The shape includes any curvature created by the border-radius property.
margin-box
Defines the shape enclosed by the outside margin edge. The corner radii of this shape are determined by the corresponding border-radius and margin values.
border-box
Defines the shape enclosed by the outside border edge. The shape follows the normal border radius shaping rules for the outside of the border.
padding-box
Defines the shape enclosed by the outside padding edge. The shape follows the normal border radius shaping rules for the inside of the border.
content-box
Defines the shape enclosed by the outside content edge. Each corner radius of this box is the larger of 0 or border-radius - border-width - padding.
<basic-shape>
The float area is computed based on the shape created by of one of inset(), circle(), ellipse(), or polygon().
<image>
The float area is extracted and computed based on the alpha channel of the specified <image> as defined by shape-image-threshold.

Shape with an image

We can combine shapes with images to get a graphical effect of the text wrapping around an image rather than around a space.

In this example, we add an image of a coffee cup and give it a class to reference it from CSS.

<h1>I'm nice, once I've
had my coffee</h1>

<img class="coffee"
src='path/to/coffee2.png' alt='coffee cup'>
<p>Dark, lungo, café au lait in latte
fair trade blue mountain strong, redeye
sugar seasonal café au lait turkish.
Black mug variety, cappuccino, single shot
 body sit grounds coffee whipped
 Turkish et, skinny …</p>

The CSS for the image (.coffee) uses shape-outside and shape-image-threshold.

When you use an image as the value for shape-outside the shape is defined by the pixels whose alpha value is greater than the threshold.

.coffee {
  shape-outside: circle(50%);
  shape-image-threshold: 0.5;
  float: left;
}

We can play with shape-outside to place text on top of the image and use images of arbitrary complexity to make our text “speak” in the voice we want.

Shapes and multiple images

Another way we can use shapes to make text flow between shapes creating custom layouts that move us outside boxes, at least visually.

The example adds two empty divs (coffee and coffee2).

<div class="coffee"></div>
<div class="coffee2"></div>
<p>Dark, lungo, café au lait in latte fair
 trade blue mountain strong, redeye sugar
 seasonal café au lait Turkish. Black mug
 variety, cappuccino, single-shot body sit
 grounds coffee whipped Turkish et, skinny,
 doppio so filter Turkish spoon affogato
 rich. Steamed roast, froth fair trade
 chicory a dripper, Turkish, extra milk,
 wings, milk dark Viennese, and est, filter,
 caffeine café au lait ut aromatic aged.</p>

The CSS defines two identical properties that create the same space on the left and right sides.

We could abstract the common elements to a third class that we can reuse but for this example, I’m ok with the duplication.

.coffee {
  shape-outside: circle(50%);
  float: left;
  height: 300px;
  width: 300px;
}

.coffee2 {
  shape-outside: circle(50%);
  float: right;
  height: 300px;
  width: 300px;
}

You can see the final product in this Codepen

A more complex example

When shapes were first released there was a companion specification for regions. This demo from the Adobe Web Platform team uses both.

Sadly, Regions are not supported in any browser other than old Edge so instead, I chose to present a video from Adobe, showing the project.