Shapes & shape-outside
Introduction to CSS Shapes and Text Wrapping
In traditional web design, text always wraps around rectangular boxes. Every element on the page is a rectangle, so when you float an image, the surrounding text flows in straight lines along the image's rectangular boundary. This creates a rigid, boxy feel that does not match the organic layouts found in print magazines, newspapers, and editorial designs where text flows gracefully around circular photos, curved illustrations, and irregular shapes.
CSS Shapes changes all of that. The shape-outside property lets you define a non-rectangular shape that text wraps around. Instead of hugging the straight edges of a floated element's box, text can flow along circles, ellipses, polygons, and even the contours of a transparent image. This unlocks editorial-quality text wrapping directly in CSS, without JavaScript hacks or manual positioning. Combined with clip-path (which you learned in the previous lesson), you can create visually stunning layouts where both the visible shape and the text wrapping follow the same contour.
How shape-outside Works
The shape-outside property defines a shape around which inline content (text) wraps. It is important to understand a critical requirement: shape-outside only works on floated elements. The element must have float: left or float: right for the shape to take effect. This is because shape-outside modifies how the float area interacts with surrounding inline content -- and only floated elements create float areas.
The shape you define with shape-outside does not change what the element looks like visually. It only changes the invisible boundary that text wraps around. To make the element's visible shape match the wrapping shape, you typically combine shape-outside with clip-path using the same shape values. Think of shape-outside as controlling the "collision boundary" for text, while clip-path controls the "visual boundary" of the element.
Basic shape-outside Syntax
/* shape-outside only works on floated elements */
.shaped-element {
float: left;
width: 200px;
height: 200px;
shape-outside: circle(50%);
}
/* Without float, shape-outside has NO effect */
.not-floated {
/* This will NOT work -- element is not floated */
shape-outside: circle(50%);
}
/* The text wrapping shape can be: */
.example {
float: left;
/* A basic shape function */
shape-outside: circle(50%);
shape-outside: ellipse(40% 50%);
shape-outside: polygon(0% 0%, 100% 0%, 50% 100%);
shape-outside: inset(10px round 20px);
/* An image with alpha channel */
shape-outside: url("shape-image.png");
/* A box value */
shape-outside: margin-box;
shape-outside: border-box;
shape-outside: padding-box;
shape-outside: content-box;
/* Reset */
shape-outside: none;
}
shape-outside is forgetting to float the element. If you apply shape-outside to a non-floated element (including flex items, grid items, or absolutely positioned elements), it will be completely ignored. Always ensure the target element has float: left or float: right.Basic Shapes with shape-outside
CSS Shapes provides the same four basic shape functions available in clip-path: circle(), ellipse(), polygon(), and inset(). When used with shape-outside, these define the contour that text wraps around.
circle()
The circle() function creates a circular wrapping area. Text flows around the curve of the circle rather than the straight edge of the rectangular box. This is the most common shape-outside value and is perfect for round avatars, circular images, and decorative elements.
Text Wrapping Around a Circle
/* Circular avatar with text wrapping */
.avatar-float {
float: left;
width: 150px;
height: 150px;
border-radius: 50%;
margin-right: 20px;
margin-bottom: 10px;
/* Text wraps around the circle instead of the rectangle */
shape-outside: circle(50%);
}
/* Circle with custom position */
.offset-circle {
float: right;
width: 200px;
height: 200px;
shape-outside: circle(50% at 50% 50%);
clip-path: circle(50%);
}
/* Smaller circle: text comes closer to center */
.tight-circle {
float: left;
width: 180px;
height: 180px;
shape-outside: circle(40%);
clip-path: circle(40%);
/* 40% radius means text wraps closer than the element edge */
}
/* Larger circle: text stays further away */
.loose-circle {
float: left;
width: 180px;
height: 180px;
shape-outside: circle(60%);
clip-path: circle(50%);
/* 60% wrapping shape is bigger than 50% visible shape */
}
shape-outside and clip-path together. The shape-outside makes text wrap around the circle shape, while clip-path visually clips the element to the same shape. Without clip-path, the element would still look rectangular even though text wraps in a curve. Without shape-outside, the element would look circular but text would still wrap around the invisible rectangle.ellipse()
The ellipse() function creates an elliptical (oval) wrapping area. It accepts two radii -- horizontal and vertical -- and an optional position. This is useful for wide or tall elements where a perfect circle does not fit the proportions.
Text Wrapping Around an Ellipse
/* Wide oval image with text wrapping */
.oval-image {
float: left;
width: 250px;
height: 180px;
margin-right: 20px;
shape-outside: ellipse(50% 50%);
clip-path: ellipse(50% 50%);
}
/* Tall narrow ellipse */
.tall-ellipse {
float: right;
width: 150px;
height: 300px;
margin-left: 20px;
shape-outside: ellipse(50% 50%);
clip-path: ellipse(50% 50%);
}
/* Off-center ellipse for artistic effect */
.artistic-ellipse {
float: left;
width: 200px;
height: 200px;
shape-outside: ellipse(45% 50% at 60% 50%);
clip-path: ellipse(45% 50% at 60% 50%);
}
polygon()
The polygon() function gives you the most control by defining a custom shape with any number of vertices. This enables text wrapping around triangles, diamonds, arrows, irregular shapes, and any contour you can describe with straight edges. Each vertex is a coordinate pair using percentages or lengths.
Text Wrapping Around Polygons
/* Triangle: text wraps along diagonal edges */
.triangle-float {
float: left;
width: 200px;
height: 200px;
shape-outside: polygon(50% 0%, 100% 100%, 0% 100%);
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
}
/* Diamond shape */
.diamond-float {
float: right;
width: 200px;
height: 200px;
margin-left: 15px;
shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
}
/* Custom angular shape */
.angular-float {
float: left;
width: 250px;
height: 300px;
shape-outside: polygon(0% 0%, 100% 0%, 100% 70%, 60% 100%, 0% 100%);
clip-path: polygon(0% 0%, 100% 0%, 100% 70%, 60% 100%, 0% 100%);
}
/* Slanted edge -- common in editorial design */
.slanted-float {
float: left;
width: 300px;
height: 400px;
shape-outside: polygon(0% 0%, 100% 0%, 70% 100%, 0% 100%);
clip-path: polygon(0% 0%, 100% 0%, 70% 100%, 0% 100%);
}
/* Arrow shape pointing into the text */
.arrow-float {
float: left;
width: 200px;
height: 150px;
shape-outside: polygon(
0% 0%, 75% 0%, 100% 50%, 75% 100%, 0% 100%
);
clip-path: polygon(
0% 0%, 75% 0%, 100% 50%, 75% 100%, 0% 100%
);
}
inset()
The inset() function creates a rectangular shape inset from the element's edges, optionally with rounded corners. While it may seem redundant (the element is already rectangular), inset() is useful for creating rounded wrapping areas that do not follow the element's sharp corners, or for creating padding between the shape and the element edge.
Text Wrapping with inset()
/* Rounded rectangle wrapping */
.rounded-float {
float: left;
width: 200px;
height: 200px;
margin-right: 20px;
shape-outside: inset(0 round 30px);
clip-path: inset(0 round 30px);
}
/* Inset with padding -- text wraps further from the element */
.padded-float {
float: right;
width: 180px;
height: 180px;
shape-outside: inset(10px round 20px);
clip-path: inset(10px round 20px);
}
/* Pill-shaped wrapping */
.pill-float {
float: left;
width: 250px;
height: 100px;
shape-outside: inset(0 round 50px);
clip-path: inset(0 round 50px);
}
shape-outside with Images
One of the most powerful features of shape-outside is the ability to use an image's alpha channel to define the wrapping shape. Instead of manually calculating polygon coordinates, you provide an image and the browser automatically traces the non-transparent areas to create the wrapping boundary. This is perfect for photos of people, products, illustrations, and any image with a transparent background.
Image-Based Shape Wrapping
/* Text wraps around the actual contour of a PNG image */
.product-float {
float: left;
width: 300px;
height: auto;
margin-right: 20px;
/* The browser traces the non-transparent pixels */
shape-outside: url("product-cutout.png");
/* Threshold: how transparent must a pixel be to count as "outside" */
shape-image-threshold: 0.5;
}
/* Person photo with transparent background */
.person-float {
float: right;
width: 250px;
margin-left: 20px;
shape-outside: url("person-cutout.png");
shape-image-threshold: 0.3;
}
/* Using the same image as the src and shape */
<img class="shaped-img"
src="irregular-shape.png"
alt="Description" />
.shaped-img {
float: left;
width: 200px;
shape-outside: url("irregular-shape.png");
shape-image-threshold: 0.5;
margin-right: 15px;
}
shape-outside, the image must be served from the same origin (same domain) or with proper CORS headers. Cross-origin images without CORS will be blocked by the browser's security policy, and the shape will fall back to the element's rectangular box. If your images are on a CDN, ensure the CDN sends the Access-Control-Allow-Origin header.shape-margin
The shape-margin property adds spacing between the defined shape and the wrapping text. It acts like an invisible buffer zone around the shape, pushing text further away from the shape's edge. Without shape-margin, text may appear too close to the shape boundary, making it hard to read. This property accepts a length value (pixels, ems, rems) or a percentage.
Adding Breathing Room with shape-margin
/* Circle with margin -- text stays away from the edge */
.avatar-with-margin {
float: left;
width: 150px;
height: 150px;
shape-outside: circle(50%);
clip-path: circle(50%);
/* 15px gap between the circle and the text */
shape-margin: 15px;
}
/* Polygon with generous margin */
.triangle-with-margin {
float: left;
width: 200px;
height: 200px;
shape-outside: polygon(50% 0%, 100% 100%, 0% 100%);
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
shape-margin: 20px;
}
/* Image-based shape with margin */
.product-with-margin {
float: right;
width: 250px;
shape-outside: url("product.png");
shape-image-threshold: 0.5;
shape-margin: 25px;
margin-left: 10px;
}
/* Different margin values for different screen sizes */
.responsive-shape {
float: left;
width: 200px;
height: 200px;
shape-outside: circle(50%);
clip-path: circle(50%);
shape-margin: 10px;
}
@media (min-width: 768px) {
.responsive-shape {
shape-margin: 20px;
}
}
@media (min-width: 1200px) {
.responsive-shape {
shape-margin: 30px;
}
}
shape-margin value is limited by the element's margin box. If the shape-margin value would push the wrapping boundary beyond the element's margin box, it gets clamped to the margin box. This means very large shape-margin values will not have any additional effect beyond the element's actual margin boundaries. Always test your shape margins visually to ensure the text has enough breathing room without creating awkward gaps.shape-image-threshold
The shape-image-threshold property controls the alpha channel threshold used when extracting a shape from an image. It defines the minimum opacity level a pixel must have to be considered part of the shape. This property accepts a value between 0.0 (fully transparent) and 1.0 (fully opaque). Pixels with an alpha value above the threshold are inside the shape; pixels below it are outside.
Controlling the Shape Extraction Threshold
/* Low threshold: even slightly visible pixels count as part of the shape */
.sensitive-shape {
float: left;
width: 200px;
shape-outside: url("soft-edge.png");
shape-image-threshold: 0.1;
/* Includes pixels that are only 10% opaque */
}
/* Default threshold: moderately transparent pixels are included */
.default-shape {
float: left;
width: 200px;
shape-outside: url("cutout.png");
shape-image-threshold: 0.5;
/* Includes pixels that are at least 50% opaque */
}
/* High threshold: only nearly-opaque pixels count */
.strict-shape {
float: left;
width: 200px;
shape-outside: url("fuzzy-edge.png");
shape-image-threshold: 0.9;
/* Only includes pixels that are 90%+ opaque */
}
/* Using a gradient image as a shape source */
.gradient-shape {
float: left;
width: 200px;
height: 300px;
/* A gradient can be used as an image for shape-outside */
shape-outside: linear-gradient(to right, black 0%, transparent 100%);
shape-image-threshold: 0.5;
/* Text wraps along the 50% opacity line of the gradient */
}
shape-outside values, just like they can be used as mask-image values. When you use a gradient, the shape-image-threshold determines where along the gradient the wrapping boundary falls. A threshold of 0.5 with a linear gradient from black to transparent creates a wrapping boundary at the midpoint of the gradient, producing a diagonal text wrap effect.Magazine-Style Text Wrapping
The primary use case for CSS Shapes is recreating the elegant text layouts found in print magazines and newspapers. In editorial design, text commonly flows around photos of people, product shots, or decorative elements in organic, non-rectangular patterns. Let us build several magazine-style layouts using shape-outside.
Magazine Layout: Author Bio with Circular Photo
<!-- HTML structure -->
<article class="author-bio">
<img class="author-photo"
src="author.jpg"
alt="Author name" />
<h3>About the Author</h3>
<p>Long biography text that wraps around the
circular author photo creating an elegant
editorial layout...</p>
</article>
<style>
.author-bio {
max-width: 600px;
line-height: 1.8;
font-size: 1.1rem;
}
.author-photo {
float: left;
width: 180px;
height: 180px;
object-fit: cover;
border-radius: 50%;
margin-right: 10px;
margin-bottom: 10px;
shape-outside: circle(50%);
shape-margin: 15px;
}
</style>
Magazine Layout: Drop Cap with Custom Shape
/* Large decorative first letter with shaped wrapping */
.article-body::first-letter {
/* Note: shape-outside does NOT work on ::first-letter */
/* We use a different technique for drop caps */
}
/* Instead, use a floated span for the drop cap */
.drop-cap {
float: left;
font-size: 5rem;
line-height: 0.8;
padding-right: 10px;
padding-top: 5px;
font-family: Georgia, serif;
color: #2c3e50;
/* The shape allows text to hug the letter shape */
shape-outside: polygon(
0% 0%, 100% 0%, 100% 100%, 60% 100%, 60% 60%, 0% 60%
);
shape-margin: 5px;
}
/* Magazine pull quote with diamond shape */
.pull-quote {
float: right;
width: 200px;
height: 200px;
margin: 0 0 20px 30px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-style: italic;
font-size: 1.1rem;
padding: 30px;
background: #f0f4f8;
shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
shape-margin: 15px;
}
Magazine Layout: Full Editorial Page
/* Large feature image floated with custom shape wrapping */
.feature-image {
float: left;
width: 45%;
max-width: 400px;
margin: 0 30px 20px 0;
/* Slanted edge creates dynamic text flow */
shape-outside: polygon(0% 0%, 100% 0%, 80% 100%, 0% 100%);
clip-path: polygon(0% 0%, 100% 0%, 80% 100%, 0% 100%);
shape-margin: 20px;
}
.feature-image img {
width: 100%;
height: auto;
display: block;
}
/* Sidebar callout with circular shape */
.sidebar-callout {
float: right;
width: 180px;
height: 180px;
margin: 10px 0 20px 25px;
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-weight: bold;
padding: 20px;
shape-outside: circle(50%);
clip-path: circle(50%);
shape-margin: 18px;
}
/* Article text styling */
.article-text {
font-size: 1.05rem;
line-height: 1.9;
color: #333;
text-align: justify;
hyphens: auto;
}
Combining shape-outside with clip-path
As we have seen in the examples above, shape-outside and clip-path are natural companions. shape-outside controls where text wraps, and clip-path controls what part of the element is visible. By using the same shape values for both properties, you create a seamless effect where the element's visible shape and its text wrapping boundary are perfectly aligned.
Synchronized shape-outside and clip-path
/* The same shape for wrapping and visibility */
.shaped-element {
float: left;
width: 250px;
height: 250px;
margin-right: 10px;
/* Both use the exact same polygon */
shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
shape-margin: 15px;
}
/* Hexagonal image */
.hex-image {
float: left;
width: 200px;
height: 230px;
object-fit: cover;
margin-right: 10px;
shape-outside: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
shape-margin: 12px;
}
/* You can use DIFFERENT shapes for wrapping vs visibility */
.creative-shape {
float: right;
width: 200px;
height: 200px;
margin-left: 15px;
/* Larger wrapping area than visible area */
shape-outside: circle(55%); /* Text wraps wider */
clip-path: circle(45%); /* Element appears smaller */
shape-margin: 10px;
/* Creates extra breathing room between shape and text */
}
/* Image-based shape with clip-path for visual matching */
.cutout-photo {
float: left;
width: 280px;
margin-right: 15px;
/* Both use the same image for consistency */
shape-outside: url("person-cutout.png");
clip-path: url(#personClipPath); /* SVG-based for smooth edges */
shape-image-threshold: 0.5;
shape-margin: 20px;
}
shape-outside and clip-path. For example, a circle for clip-path paired with a slightly larger circle for shape-outside creates visual padding between the element's edge and the wrapping text. This technique is useful when shape-margin alone does not give you enough control over the spacing.Creative Editorial Layouts
Let us push the boundaries of CSS Shapes to create truly creative editorial layouts that would make any print designer proud. These examples demonstrate advanced techniques combining multiple floated shapes, custom polygons, and image-based contours.
Two-Sided Text Wrapping
/* Text wraps around shapes on BOTH sides */
.two-sided-layout {
max-width: 800px;
margin: 0 auto;
line-height: 1.8;
}
.left-shape {
float: left;
width: 150px;
height: 300px;
shape-outside: polygon(0% 0%, 100% 10%, 80% 50%, 100% 90%, 0% 100%);
clip-path: polygon(0% 0%, 100% 10%, 80% 50%, 100% 90%, 0% 100%);
background: linear-gradient(180deg, #e74c3c, #c0392b);
shape-margin: 15px;
}
.right-shape {
float: right;
width: 150px;
height: 300px;
shape-outside: polygon(100% 0%, 0% 10%, 20% 50%, 0% 90%, 100% 100%);
clip-path: polygon(100% 0%, 0% 10%, 20% 50%, 0% 90%, 100% 100%);
background: linear-gradient(180deg, #3498db, #2980b9);
shape-margin: 15px;
}
/* Text flows between the two shapes creating a narrow channel */
Text Wrapping Around a Product Photo
/* Product showcase: text hugs the product contour */
.product-showcase {
max-width: 700px;
line-height: 1.8;
font-size: 1.05rem;
}
.product-image {
float: left;
width: 350px;
margin: 0 25px 15px 0;
/* Image-based shape traces the product outline */
shape-outside: url("headphones-cutout.png");
shape-image-threshold: 0.4;
shape-margin: 20px;
}
.product-image img {
width: 100%;
height: auto;
/* clip-path not needed since the PNG already has transparency */
}
/* Fallback for browsers without shape support */
@supports not (shape-outside: url("test.png")) {
.product-image {
border-radius: 20px;
margin-right: 30px;
}
}
Story Layout with Multiple Shapes
/* Complex editorial layout with stacked shapes */
.story-layout {
max-width: 800px;
line-height: 1.9;
column-count: 2;
column-gap: 40px;
}
/* First image: circular, floated left in first column */
.story-image-1 {
float: left;
width: 180px;
height: 180px;
object-fit: cover;
margin: 0 15px 15px 0;
shape-outside: circle(50%);
clip-path: circle(50%);
shape-margin: 12px;
}
/* Second image: diamond, floated right */
.story-image-2 {
float: right;
width: 160px;
height: 160px;
object-fit: cover;
margin: 0 0 15px 15px;
shape-outside: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
shape-margin: 15px;
}
/* Third image: custom contour from PNG */
.story-image-3 {
float: left;
width: 250px;
margin: 0 20px 15px 0;
shape-outside: url("illustration.png");
shape-image-threshold: 0.5;
shape-margin: 18px;
}
Responsive Considerations
CSS Shapes require special attention for responsive design. Floated elements with shapes can cause layout problems on small screens where there is not enough room for text to flow around the shape. A 200-pixel-wide circle on a 320-pixel-wide screen leaves very little room for readable text. You must plan for these scenarios to ensure your editorial layouts degrade gracefully on mobile devices.
Making Shape Layouts Responsive
/* Base layout: no shapes on mobile */
.editorial-image {
display: block;
width: 100%;
max-width: 400px;
margin: 0 auto 20px;
border-radius: 12px;
}
/* Enable shapes only on screens wide enough for text flow */
@media (min-width: 768px) {
.editorial-image {
float: left;
width: 250px;
margin: 0 25px 15px 0;
border-radius: 0;
shape-outside: circle(50%);
clip-path: circle(50%);
shape-margin: 15px;
}
}
@media (min-width: 1024px) {
.editorial-image {
width: 300px;
shape-margin: 25px;
}
}
/* Another approach: simplify the shape on smaller screens */
.complex-shape {
float: left;
width: 200px;
height: 200px;
}
@media (min-width: 768px) {
.complex-shape {
shape-outside: circle(50%);
clip-path: circle(50%);
shape-margin: 15px;
}
}
@media (min-width: 1024px) {
.complex-shape {
/* More complex shape on larger screens */
shape-outside: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
shape-margin: 20px;
}
}
/* Clear floats when text gets too cramped */
@media (max-width: 500px) {
.shaped-float {
float: none;
shape-outside: none;
clip-path: none;
width: 100%;
margin: 0 0 20px 0;
}
}
shape-outside and float on screens where the text column would be less than 200 pixels wide.Browser Support
CSS Shapes (shape-outside, shape-margin, shape-image-threshold) have good support in all modern browsers. Chrome, Edge, Safari, Opera, and Firefox all support the full specification. Internet Explorer does not support CSS Shapes at all, but it is essentially defunct. The key consideration is that shapes are a progressive enhancement -- when they are not supported, text simply wraps around the rectangular box as usual, so the content remains fully accessible and readable.
Progressive Enhancement with Feature Queries
/* Base styles: works everywhere */
.author-image {
float: left;
width: 180px;
height: 180px;
border-radius: 50%;
margin-right: 20px;
margin-bottom: 10px;
object-fit: cover;
}
/* Enhanced styles: only when shapes are supported */
@supports (shape-outside: circle(50%)) {
.author-image {
shape-outside: circle(50%);
shape-margin: 15px;
margin-right: 5px;
/* Reduce margin since shape-margin handles spacing */
}
}
/* Full feature detection with image shapes */
@supports (shape-outside: url("test.png")) {
.product-photo {
shape-outside: url("product.png");
shape-image-threshold: 0.5;
shape-margin: 20px;
}
}
/* Fallback for very old browsers: no float at all */
@supports not (shape-outside: circle(50%)) {
.shaped-element {
/* Optionally remove float entirely for a simpler layout */
float: none;
display: block;
margin: 0 auto 20px;
width: 100%;
max-width: 300px;
}
}
Practical Examples
Let us build complete, production-ready examples that demonstrate CSS Shapes in realistic scenarios. Each example includes the full HTML structure and CSS needed to recreate the layout.
Blog Post with Author Avatar
<!-- HTML -->
<article class="blog-post">
<h1>Understanding Modern CSS Layout</h1>
<div class="post-meta">
<img class="author-avatar"
src="author-avatar.jpg"
alt="Sarah Chen" />
<div class="post-content">
<p>CSS has evolved dramatically over the past decade.
From the early days of table-based layouts to the
modern era of Grid and Flexbox, the way we build
web pages has been completely transformed...</p>
<p>The introduction of CSS Shapes adds yet another
dimension to our layout capabilities, allowing
text to flow around non-rectangular shapes for
the first time in CSS history...</p>
</div>
</div>
</article>
<style>
.blog-post {
max-width: 680px;
margin: 0 auto;
padding: 40px 20px;
font-family: Georgia, serif;
line-height: 1.8;
color: #2c3e50;
}
.blog-post h1 {
font-size: 2rem;
margin-bottom: 30px;
}
.author-avatar {
float: left;
width: 120px;
height: 120px;
object-fit: cover;
border-radius: 50%;
margin-right: 5px;
margin-bottom: 10px;
}
@supports (shape-outside: circle(50%)) {
.author-avatar {
shape-outside: circle(50%);
shape-margin: 15px;
}
}
</style>
Product Landing Page with Shape Wrapping
<!-- HTML -->
<section class="product-section">
<img class="product-hero"
src="smartphone-cutout.png"
alt="New Smartphone Model" />
<h2>The Future of Mobile</h2>
<p>Our latest smartphone features a revolutionary
edge-to-edge display, advanced AI capabilities,
and the most powerful camera system we have
ever created. With a sleek design that fits
perfectly in your hand, it redefines what a
mobile device can be...</p>
<p>The ultra-wide lens captures breathtaking
landscapes, while the macro lens reveals
details invisible to the naked eye. Combined
with our neural image processing engine,
every photo is a masterpiece...</p>
</section>
<style>
.product-section {
max-width: 750px;
margin: 0 auto;
padding: 40px 20px;
line-height: 1.8;
font-size: 1.1rem;
}
.product-hero {
width: 100%;
max-width: 300px;
display: block;
margin: 0 auto 20px;
}
@media (min-width: 768px) {
.product-hero {
float: right;
width: 280px;
margin: 0 0 20px 30px;
shape-outside: url("smartphone-cutout.png");
shape-image-threshold: 0.4;
shape-margin: 25px;
}
}
</style>
Quote Block with Decorative Shape
/* Decorative quote with angled shape */
.quote-block {
position: relative;
max-width: 700px;
margin: 40px auto;
padding: 0 20px;
line-height: 1.8;
}
.quote-decoration {
float: left;
width: 80px;
height: 80px;
background: linear-gradient(135deg, #f39c12, #e67e22);
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
color: white;
font-family: Georgia, serif;
margin-right: 5px;
margin-bottom: 5px;
shape-outside: polygon(0% 0%, 100% 0%, 100% 100%);
clip-path: polygon(0% 0%, 100% 0%, 100% 100%);
shape-margin: 10px;
}
.quote-text {
font-size: 1.2rem;
font-style: italic;
color: #555;
}
.quote-attribution {
display: block;
margin-top: 15px;
font-style: normal;
font-weight: bold;
color: #333;
}
Interactive Shape Change on Hover
/* Note: shape-outside does NOT support transitions/animations */
/* But we can toggle shapes using classes with JavaScript */
.morphable-float {
float: left;
width: 200px;
height: 200px;
margin-right: 10px;
background: url("photo.jpg") center/cover;
transition: clip-path 0.4s ease;
/* Default: circle */
shape-outside: circle(50%);
clip-path: circle(50%);
shape-margin: 15px;
}
/* JavaScript toggles this class */
.morphable-float.hexagon {
shape-outside: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}
/* Script to toggle shape */
<script>
const el = document.querySelector('.morphable-float');
el.addEventListener('click', () => {
el.classList.toggle('hexagon');
/* Note: text reflow happens immediately;
only clip-path animates visually */
});
</script>
clip-path, the shape-outside property cannot be animated or transitioned with CSS. Changing the shape-outside value causes the text to reflow immediately without any smooth transition. If you need animated shape changes with text wrapping, you must use JavaScript to toggle classes, and the text reflow will be instant while the visual clip-path change can still be animated smoothly.Exercise 1: Magazine Article with Image Wrapping
Create a magazine-style article layout. Start with a large hero image at the top that spans the full width. Below it, float a circular author photo to the left using shape-outside: circle(50%) with shape-margin: 20px and a matching clip-path. The first two paragraphs of text should wrap around the circle. Then add a rectangular pull quote floated to the right with a diamond shape-outside using polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%). The pull quote should have a background color and centered italic text. Further down the article, float a product image (with a transparent PNG background) to the left, using shape-outside: url() with shape-image-threshold: 0.5 so text wraps tightly around the product's actual contour. Add shape-margin: 25px for breathing room. Make the layout responsive: on screens narrower than 768px, remove all floats and shapes so images stack vertically above the text. Use @supports (shape-outside: circle(50%)) for progressive enhancement.
Exercise 2: Creative Portfolio Showcase
Build a portfolio showcase section with three project entries. Each entry has a project image floated alternately left and right (first left, second right, third left). For the first entry, use shape-outside: polygon() with a slanted edge (e.g., polygon(0% 0%, 100% 0%, 85% 100%, 0% 100%)) so text flows along the diagonal. For the second entry (floated right), use shape-outside: circle(50%) for a circular text wrap. For the third entry, use shape-outside: ellipse(50% 40%) for an oval wrap. Each floated image should have a matching clip-path and a shape-margin of 20px. Add a clearfix between entries so each one starts on a new line. Use CSS Grid or simple block layout for the overall structure. On screens below 600px wide, remove all shapes and floats, displaying each project as a stacked card with the image above the description. Include @supports queries to gracefully degrade for any browser that does not support shape-outside.