The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Wrap around a circle | .portrait {
float: inline-start;
shape-outside: circle(50%);
} | View examples |
| Give the float dimensions | .portrait { inline-size: 12rem; aspect-ratio: 1; } | View examples |
| Wrap an ellipse | .photo { shape-outside: ellipse(48% 42% at 50% 48%); } | View examples |
| Round an inset rectangle | .note { shape-outside: inset(0 8% 0 0 round 1.5rem); } | View examples |
| Wrap a polygon | .cutout {
shape-outside: polygon(0 0, 100% 0, 72% 100%, 0 100%);
} | View examples |
| Choose the fill rule | .star {
shape-outside:
polygon(evenodd, 50% 0, 100% 100%, 0 38%, 100% 38%, 0 100%);
} | View examples |
| Use SVG path data | .wave {
shape-outside:
path('M0,0 C80,20 20,180 100,200 L0,200 Z');
} | View examples |
| Use the margin edge | .pullquote { shape-outside: margin-box; } | View examples |
| Select a reference box | .portrait { shape-outside: circle(50%) content-box; } | View examples |
| Add breathing room | .portrait { shape-margin: clamp(0.5rem, 2vw, 1.25rem); } | View examples |
| Disable narrow wrapping | @media (max-width: 36rem) {
.portrait { float: none; shape-outside: none; };
} | View examples |
| Wrap image alpha | .silhouette {
shape-outside: url('/images/leaf-alpha.png');
} | View examples |
| Choose the alpha threshold | .silhouette { shape-image-threshold: 0.35; } | View examples |
| Shape from a gradient | .fade {
shape-outside:
linear-gradient(90deg, #000 65%, transparent 65%);
} | View examples |
| Match visual clipping | .portrait {
clip-path: circle(50%);
shape-outside: circle(50%);
} | View examples |
| Guard shape enhancement | @supports (shape-outside: circle(50%)) {
.portrait { shape-outside: circle(50%); };
} | View examples |
CSS Shapes changes the exclusion contour used by inline content next to a float; it does not visually clip the floated element and it does not reshape arbitrary in-flow or positioned boxes. Begin with a correctly sized float that gives a rectangular fallback, then describe its wrap contour with a basic shape, box edge, or image alpha. Keep reading order logical, leave generous space with shape-margin, and test narrow layouts where elaborate wrapping can produce very short lines.
Step by step
Detailed examples
Establish a real float and a useful rectangle first
shape-outside applies to floats (and, in the specification, initial-letter boxes), so setting it on an ordinary in-flow element does not make surrounding text wrap. Give the float definite geometry and a logical float direction. Browsers that ignore the shape still wrap against its margin box, making the rectangular float your progressive-enhancement baseline.
.portrait {
float: inline-start;
inline-size: clamp(8rem, 30vi, 14rem);
aspect-ratio: 1;
margin-inline-end: 1rem;
shape-outside: circle(50%);
border-radius: 50%;
object-fit: cover;
} Describe common contours with circle, ellipse, and inset
circle() and ellipse() accept radii plus an optional at-position; percentage radii resolve from the selected reference box. inset() creates a rectangle inset from its reference box and accepts border-radius-like rounding. These functions define the wrap area only—use border-radius or clip-path separately if the pixels should have the same silhouette.
.avatar { shape-outside: circle(48% at 50% 50%); }
.oval { shape-outside: ellipse(48% 40% at 50% 48%); }
.rounded-note { shape-outside: inset(0 8% 0 0 round 1.5rem); }
:is(.avatar, .oval, .rounded-note) {
float: inline-start;
inline-size: 12rem;
block-size: 12rem;
} Build custom contours while understanding their coordinate systems
polygon() joins percentage or length coordinate pairs and scales naturally when percentages are used. Its optional fill rule matters for self-intersections. path() accepts SVG path data and provides curves, but ordinary numeric path coordinates use a fixed user coordinate system, making them less responsive. Keep point counts manageable and test concave shapes for unexpectedly narrow line fragments.
.wedge {
float: inline-end;
inline-size: 40%;
block-size: 16rem;
shape-outside: polygon(28% 0, 100% 0, 100% 100%, 0 100%);
}
.wave {
float: inline-start;
inline-size: 100px;
block-size: 200px;
shape-outside: path('M0,0 C80,20 20,180 100,200 L0,200 Z');
} Choose which box supplies the shape coordinates
A basic shape may be paired with margin-box, border-box, padding-box, or content-box. The shape is calculated from that box, while the float's margin box still bounds how far the exclusion can extend. With only a box keyword, the box edge and relevant corner radii form the contour. State the box explicitly when padding or borders would otherwise make percentage coordinates surprising.
.pullquote {
float: inline-start;
inline-size: 12rem;
padding: 1rem;
margin: 0 1rem 1rem 0;
border-radius: 2rem;
shape-outside: margin-box;
}
.portrait {
shape-outside: circle(50%) content-box;
} Protect line length with margins and responsive escape hatches
shape-margin expands the computed contour by a non-negative length or percentage and is the right way to create consistent breathing room. It cannot pull text inward with a negative value. At narrow widths, floating a large shape can leave only a few words per line, so disable the float and shape together and allow the media to return to normal flow.
.portrait {
shape-margin: clamp(.5rem, 2vw, 1.25rem);
}
@media (max-width: 36rem) {
.portrait {
float: none;
display: block;
margin-inline: auto;
shape-outside: none;
}
} Derive a contour from transparent pixels safely
An image value makes the alpha channel define the contour; shape-image-threshold chooses which pixels count as inside, and shape-margin expands the result. External images must be fetched successfully and be CORS-safe for shape extraction or the shape behaves as none. A CSS gradient avoids a network dependency. Keep a meaningful rectangular float because image failures should not destroy the layout.
.silhouette {
float: inline-start;
inline-size: 14rem;
block-size: 18rem;
shape-outside: linear-gradient(90deg, #000 70%, transparent 70%);
shape-margin: .75rem;
}
@supports (shape-outside: url('/images/leaf-alpha.png')) {
.silhouette {
shape-outside: url('/images/leaf-alpha.png');
shape-image-threshold: .35;
}
} Align paint and wrapping without confusing their roles
shape-outside changes wrapping, whereas clip-path changes painting and hit testing. Declare both when a visible crop must match the exclusion contour. Do not put meaningful prose into a decorative float merely to obtain a shape: DOM reading order and accessibility remain unchanged by visual wrapping. Use @supports for enhanced contours and test zoom, selection, and long unbreakable text.
.portrait {
float: inline-start;
inline-size: 12rem;
aspect-ratio: 1;
border-radius: 50%;
}
@supports (shape-outside: circle(50%)) {
.portrait {
shape-outside: circle(50%);
clip-path: circle(50%);
shape-margin: .75rem;
}
} Local code tester
Wrap an article around a responsive profile shape
Change the shape, margin, or width and observe how the rectangular float fallback remains coherent.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



