Wrap Text Around Shapes: Circle, Ellipse, Polygon
Text wrap around geometric shapes was long an unfulfilled wish in web design. CSS shape-outside makes it possible: text flows around circles, ellipses, and polygons, using floats, without JavaScript, directly in CSS. shape-margin, shape-image-threshold, and clip-path complete the toolkit for editorial web design.
Table of Contents
- 1. Why Text Wrap Around Shapes Matters
- 2. Float as a Prerequisite for shape-outside
- 3. shape-outside with circle()
- 4. shape-outside with ellipse()
- 5. shape-outside with polygon()
- 6. shape-outside with inset()
- 7. shape-margin: Spacing Around the Shape
- 8. Text Wrap Around Image Shapes with shape-image-threshold
- 9. shape-outside Shapes Compared
- 10. Summary
- 11. FAQ
1. Why Text Wrap Around Shapes Matters
Classic print design thrives on text wrapping around images, illustrations, and decorative elements: a curved contour line around a portrait photo, a text block that follows a diagonal banner, a pull quote that the body text wraps around. On the web, this remained a wish for a long time: CSS could only flow text past rectangular boxes. The result was usually blocky, unappealing layouts that lagged far behind printed media. CSS shape-outside closes this gap and brings genuine geometric text wrap to web design.
The shape-outside property is part of the CSS Shapes Module Level 1 specification and is supported by all modern browsers. It defines a shape around which the surrounding flow text wraps. It is important to understand that shape-outside does not change the visual appearance of the float itself, that is handled by clip-path or other styling. shape-outside exclusively affects how adjacent inline content flows around the floated element. This separation of shape and appearance is one of the more design oriented concepts in CSS.
2. Float as a Prerequisite for shape-outside
CSS shape-outside only works in combination with floated elements. This is a hard technical constraint of the specification: an element must have float: left or float: right for shape-outside to take effect. Without a float, browsers ignore the shape-outside property. This makes float, often considered outdated in the age of Flexbox and Grid, relevant again for this specific use case.
Floated elements with shape-outside also require explicit dimensions: width and height must be set so the shape functions have a reference frame. Without dimensions, geometric shape functions like circle() and polygon() do not work correctly. The content area around the float needs enough room for the text wrap to be visible; if the container is too narrow, there is no visible difference from a plain float. A common setup: a floated element on the left or right, with flow text in a <p> block without a float that wraps around the floated area.
/* shape-outside requires float, these are the essential rules */
.float-shape {
float: left; /* Required, no shape-outside without float */
width: 250px; /* Required, defines the coordinate space */
height: 250px; /* Required for most shape functions */
margin-inline-end: 1.5rem; /* Space between shape and following content */
shape-outside: circle(50%); /* Text flows around a circle */
clip-path: circle(50%); /* Visually clip the element to circle too */
}
/* Without clip-path: shape-outside applies to text flow only */
/* The element itself still looks like a rectangle */
.float-shape-right {
float: right;
width: 200px;
height: 300px;
shape-outside: ellipse(50% 60% at 50% 50%);
shape-margin: 1rem; /* Extra space between shape outline and text */
}
/* Clearfix for the container, prevent collapse */
.text-wrap-container::after {
content: "";
display: table;
clear: both;
}
3. shape-outside with circle()
The simplest and most common shape function is circle(). The full syntax is circle(<radius> at <cx> <cy>). All parameters are optional: circle(50%) creates a circle at 50% of the element's shorter dimension, centered. The radius can be given in absolute units (px, em, rem) or as a percentage. Percentage values are relative to the hypothetical length of the element's diagonal divided by the square root of 2.
The position argument at <cx> <cy> shifts the circle's center point. circle(50% at 0% 50%) creates a circle centered on the left edge of the element, a half circle effect that draws text into a curve. Combined with clip-path: circle(50%) on the same element, the element is visually rendered as a circle and the text wraps around the circular silhouette. This is the typical pattern for round profile images with CSS shape-outside, frequently used in editorial layouts and author boxes.
/* shape-outside circle(): author portrait with text wrap */
.author-portrait {
float: left;
width: 180px;
height: 180px;
shape-outside: circle(50%);
clip-path: circle(50%); /* Visually matches the shape */
shape-margin: 1.25rem;
margin-block-end: 0.5rem;
object-fit: cover; /* For <img> elements */
}
/* Half-circle variant, text wraps around the curved side only */
.hero-image-left {
float: left;
width: 300px;
height: 400px;
shape-outside: circle(55% at 100% 50%);
/* Circle centered at right edge, creates concave text boundary */
clip-path: inset(0 0 0 0 round 0 50% 50% 0);
}
/* Decorative circle that pushes text into a column */
.pull-quote-ornament {
float: right;
width: 120px;
height: 120px;
background: radial-gradient(circle, #7c3aed, #4a1d96);
shape-outside: circle(60px at center);
shape-margin: 1.5rem;
border-radius: 50%;
}
4. shape-outside with ellipse()
The ellipse() function in CSS shape-outside extends circle() with a second radius axis: ellipse(<rx> <ry> at <cx> <cy>). The first radius rx sets the horizontal extent, the second ry the vertical extent. This creates oval shapes that suit certain image content better than a perfect circle. A portrait photo looks more natural with a vertically stretched ellipse, while a landscape image suits a horizontally stretched shape.
ellipse() is especially interesting for decorative elements in editorial layouts. An illustration in a news blog, a product photo in a magazine style layout, an author illustration: all of these fit naturally into flow text with ellipse(). The at positioning allows asymmetric placements: ellipse(40% 60% at 30% 50%) shifts the ellipse's center of gravity to the left and produces a text wrap that offers more room on one side than the other. This enables dynamic, asymmetric layouts with pure CSS.
5. shape-outside with polygon()
The most powerful shape function is polygon(). It takes a list of x,y coordinate pairs and creates an arbitrary polygon. polygon(0 0, 100% 0, 100% 50%, 50% 100%, 0 50%) creates a pentagon. polygon() allows both concave and convex shapes, so in principle any silhouette can be represented as long as it can be approximated as a polygon. Coordinates can be given in absolute units or as percentages of the element's box.
A practical tool for CSS shape-outside polygon() is the Firefox DevTools shape path editor, or online tools like a CSS clip path maker. These tools let you drag polygon points visually and take over the generated coordinates directly. When combining a polygon() shape with a clip-path, it is important that both functions use the same coordinates, otherwise a visual mismatch appears between the element's visible shape and the text wrap around the element.
/* shape-outside polygon(): complex shapes for editorial layouts */
/* Diamond / rhombus text wrap */
.diamond-ornament {
float: left;
width: 200px;
height: 200px;
shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
background: linear-gradient(135deg, #7c3aed, #c4b5fd);
shape-margin: 1rem;
}
/* Diagonal cut, text wraps along a diagonal line */
.diagonal-image {
float: right;
width: 280px;
height: 360px;
shape-outside: polygon(20% 0%, 100% 0%, 100% 100%, 0% 100%);
/* Text flows around the diagonal cut on the left side */
clip-path: polygon(20% 0%, 100% 0%, 100% 100%, 0% 100%);
object-fit: cover;
}
/* Arrow / chevron pointing right */
.chevron-accent {
float: left;
width: 80px;
height: 160px;
shape-outside: polygon(0% 0%, 100% 50%, 0% 100%);
clip-path: polygon(0% 0%, 100% 50%, 0% 100%);
background: #4a1d96;
shape-margin: 1.5rem;
}
/* Circular image with transparent areas, image URL version */
.cutout-image {
float: left;
width: 250px;
height: 350px;
/* shape-image-threshold: 0.5, alpha above 0.5 counts as inside shape */
shape-outside: url('/media/product-cutout.png');
shape-image-threshold: 0.5;
shape-margin: 0.75rem;
}
6. shape-outside with inset()
The inset() function in CSS shape-outside creates a rectangle that is indented from the element's edges. The syntax follows box model logic: inset(top right bottom left) with an optional round <border-radius>. inset(10px 20px 10px 20px round 15px) creates a rounded rectangle indented on every side.
At first glance, inset() sounds unexciting, a rectangle is, after all, the default behavior of a float. Its value lies in the possibilities it opens up: indenting with different values creates asymmetric text wrap areas without altering the element itself. The round argument creates rounded text wrap boundaries that can be combined with a clip-path: inset(... round ...) on the element itself. inset() is also useful when you need a large gap on one side and none on the other, for example to let a caption text extend into the float area.
7. shape-margin: Spacing Around the Shape
The shape-margin property adds an outer margin around the defined shape, around which the text then flows. The difference from the regular CSS margin property: margin shifts the element and enlarges the float box. shape-margin only enlarges the geometric text wrap distance without shifting the element or changing the float box. The effect is an even buffer between the lines of text and the shape boundary.
shape-margin accepts length values in px, em, rem, or percentages relative to the containing block's width. With percentage values, the spacing changes with the container width, which can be useful for responsive designs. Important: shape-margin cannot extend the shape beyond the boundaries of the float box. If the computed shape-margin value is larger than the distance between the shape and the float box edge, it is clamped to the available space. This means shape-margin can have no effect on very small float boxes.
8. Text Wrap Around Image Shapes with shape-image-threshold
A particularly powerful capability of CSS shape-outside is the ability to use an image URL as a shape. With shape-outside: url('image.png'), the browser extracts the image's alpha channel information and computes the shape from the non-transparent area. shape-image-threshold controls at which alpha value a pixel counts as "inside the shape": shape-image-threshold: 0.5 means pixels with more than 50% opacity define the shape boundary.
This allows elaborate cutout images to be used directly as text wrap boundaries, a feature that used to be available only in desktop publishing software. A product photo with a transparent background, a silhouette, an illustrated figure: the text flows exactly around the real contour, not around a bounding rectangle. The constraint: the image must be loadable in a CORS compatible way. Same origin images always work; cross origin images require correct CORS headers, otherwise the browser ignores the shape-outside instruction.
9. shape-outside Shapes Compared
The four shape functions of CSS shape-outside cover different use cases. The choice between them depends on the desired text wrap geometry and the type of floated element.
| Function | Syntax Example | Typical Use | Special Trait |
|---|---|---|---|
| circle() | circle(50%) |
Profile images, round ornaments | Simplest shape, a perfect circle |
| ellipse() | ellipse(40% 60% at center) |
Portrait photos, oval decorations | Two independent radii, oval |
| polygon() | polygon(50% 0, 100% 100%, 0 100%) |
Diagonal cuts, triangles, arrows | Arbitrary polygons, maximum freedom |
| inset() | inset(10px round 12px) |
Rounded rectangles, asymmetric indents | Extends float box logic with rounding |
| url() | url('cutout.png') |
Cutout photos, illustrations | Alpha channel defines shape, CORS required |
In practice the following rule of thumb applies: circle() for all round images and ornaments, fast, readable, maintainable. ellipse() for portrait format cutouts. polygon() for decorative curved or diagonal elements, where a shape editor helps. inset() for subtle adjustments to rectangular floats with rounding. The url() variant is the most powerful tool for genuine cutout product images, when CORS and performance allow, but it requires careful image optimization.
10. Summary
CSS shape-outside is a well supported but underused CSS property that enables genuine text wrap around geometric shapes. The core requirement is a float: without float: left or float: right, shape-outside does not work. The shape functions circle(), ellipse(), polygon(), and inset() cover the entire spectrum from round profile images to diagonal cuts to arbitrary polygons. shape-margin adds a buffer around the shape without shifting the element.
For editorial web design, article pages, landing pages, product descriptions, CSS shape-outside offers design possibilities that were previously only possible in print media. Combined with clip-path for the visual appearance and shape-image-threshold for cutout images, it forms a complete system for curved, dynamic layouts without JavaScript. Browser support is excellent: all modern browsers fully support CSS shape-outside.
CSS shape-outside: The Essentials at a Glance
Requirement
float: left or float: right, no shape-outside without a float. Set explicit width and height for the floated element.
Shapes
circle(), ellipse(), polygon(), inset(). For cutout images: url() plus shape-image-threshold. clip-path for visually matching the element.
shape-margin
Spacing between the shape boundary and flow text. Does not change the element, only the text wrap buffer. Capped by the float box edge.
Browser Support
All modern browsers, no fallback needed. The url() variant requires CORS compatible images for cross origin sources.
Mironsoft
Editorial Web Design, Hyvä Themes, and Modern CSS
Magazine Layouts with CSS: No JavaScript?
We design editorial Magento and Hyvä layouts with CSS shape-outside, clip-path, and modern text wrap techniques, for product pages, blog articles, and landing pages that stand out from the crowd.
Editorial Design
shape-outside for blog articles and CMS content, text wrap around product images and illustrations
Cutout Integration
shape-image-threshold for product photos with transparent backgrounds, genuine text wrap around the contour
Landing Pages
Diagonal cuts, polygon shapes, and parallax for landing pages with print design quality