CSS shape-outside: Wrap Text Around Shapes

Wrap text around shapes without dummy floats

A floated circle still wraps like a box. border-radius only changes the paint. Dummy floated spans used to stair-step the text. shape-outside sets the wrap contour, so lines follow the shape.

Old wayborder-radius only
.avatar  {  float: left;  width: 160px;  height: 160px;  border-radius: 50%;}/* looks round, wrap is still a rectangle */
shape-outside
.avatar  {  float: left;  shape-outside: circle(50%);  shape-margin: 1rem;}/* wrap follows the circle, not the box */
Widely availableSince 202096% global usage

This feature is well established and works across many devices and browser versions. It has been available across browsers since 2020.

Safe to use without fallbacks.

37+
62+
10.1+
79+
text follows the circle, not the box

Float plus border-radius still wraps a rectangle. The circle is visual only. Each line stops at the box edge, then jumps past it.

border-radius only

shape-outside: circle(50%) sets the wrap contour. Lines follow the curve instead of the box. shape-margin keeps a gap off the edge.

shape-outside: circle(50%)

Wrap follows the contour

border-radius rounds the paint. Inline content still hugs the margin box. shape-outside changes that contour, so lines follow a circle, ellipse, or polygon.

No dummy floats

The old fake was a stack of empty floated spans of decreasing width, the sandbag technique. One property replaces the whole staircase.

Visual and wrap stay separate

clip-path hides pixels. shape-outside only changes how neighbors wrap. Pair them, or keep border-radius for the look and shape-outside for the wrap.

Old Approach
float + border-radius
Looks round, wraps a box
Modern Approach
shape-outside
Wrap follows the contour
Applies to
floats only
No effect on in-flow boxes

How it works

A floated image with border-radius: 50% looks circular. Inline text still wraps the rectangular margin box. The old workaround was dummy floats, empty spans of decreasing width stacked down the side so the text stair-stepped around the circle.

shape-outside: circle(50%) sets the wrap contour from the element's box. ellipse(), inset(), and polygon() do the same with other geometries. shape-margin pushes the text away from that contour. url() uses the image alpha channel, so text can hug an irregular PNG, with CORS applying the same way it does for canvas.

The property only applies to floats. An in-flow circle ignores it. clip-path is a different job: it hides pixels, it does not change wrapping. For a circular avatar, border-radius plus shape-outside: circle(50%) is the usual pair. For a clipped polygon, the same coordinates often go in both properties.

ESC