Movatterモバイル変換


[0]ホーム

URL:


Skip to content
A List Apart

A List Apart

For people who make websites

CSS Shapes 101

by
Published inCode,CSS

Rectangles inside other rectangles: this is what our webpages have always been made of. We’ve long tried to break free from their restrictions by using CSS to creategeometric shapes, but those shapes have never affected the content inside the shaped element, or how the element is seen by other elements on the page.

Article Continues Below

The new CSS Shapes specification is changing that. Introduced byAdobe in mid-2012, its goal is to provide web designers with a new way to change how the content flows inside and around arbitrarily complex shapes—something we’ve never been able to do before, not even with JavaScript.

For example, notice how the text flows around the circular images in the following design. Without Shapes, the text would be rectangular—throwing off the sophisticated touch that takes the design to the next level.

Image of a magazine layout with text wrapped around circular shaped images.
Notice how the text wraps around the circular shape of a bowl in this example. Using CSS Shapes, we can create similar designs for the web.

Let’s walk through how Shapes work, and how you can start using them.

Browser support#section2

CSS Shapes are currently supported only in Webkit Nightly and Chrome Canary, but its Module Level 1 has reached the Candidate Recommendation status, so the properties and syntax defined in the spec are pretty stable. It won’t be long before they’re implemented in other browsers. This level focuses on the Shapes properties that change the flow of contentaround a shape. More specifically, it focuses on theshape-outside property and its related properties.

Combined with other cutting-edge features such asClipping and Masking,CSS Filters, andCompositing and Blending, CSS Shapes will allow us to create more polished and sophisticated designs without having to resort to graphics editors like Photoshop or InDesign.

Future levels of CSS Shapes will focus on wrapping content inside a shape as well. For example, today it’s easy to create a rhombic shape in CSS: just rotate the element by 45 degrees, and then rotate the content inside it back so that it lies horizontally on the page. But the content inside the rhombus won’t be affected by the rhombic shape of its container, and will always remain rectangular. When the CSS Shapesshape-inside property is implemented, we will be able to make the content also become rhombic, making layouts like the one shown in the following image very much possible.

Image of a magazine layout using rhombic shapes.
Soon, CSS Shapes will also allow text inside shapes, like these rhombuses, to adjust to the edges of its container, rather than overflow or get cut off.

In order to use CSS Shapes in Chrome Canary today, you have to enable the experimental features flag. If you’re not sure how to do that, have a look atthis walkthrough on the Adobe blog.

Creating a CSS Shape#section3

You can apply a shape to an element using one of the Shapesproperties. You pass the shape property a shapefunction as a value. The shape function is where you pass in arguments that define the shape that you want to apply to the element.

Illustration showing different parts making up a shape rule.

Shapes can be created using one of the following functions:

  • circle()
  • ellipse()
  • inset()
  • polygon()

Each shape is defined by a set of points. Some functions take points as parameters; others take offsets—but they all eventually draw the shapes as a set of points on the element. We’ll cover the parameters for each of these functions in the examples we’re going to create.

A shape can also be defined by extracting it from an image with an alpha channel. When an image is passed to a shape property, the browser then extracts the shape from the image based on ashape-image-threshold. The shape is defined by the pixels whose alpha value is greater than the threshold. The image must beCORS compatible. If the image provided cannot be displayed for any reason (such as if it doesn’t exist), then no shape will be applied.

The shape properties that accept the above functions as values are:

  • shape-outside: Wraps content around (outside) a shape
  • shape-inside: Wraps content inside a shape

You can use theshape-outside property in conjunction with theshape-margin property to add a margin around the shape that pushes the flowing content away from the shape, creating more room between it and the content. Just likeshape-outside gets ashape-margin property,shape-inside gets ashape-padding property, which adds inner padding.

Using the shape properties and functions, declaring a shape on an element can be as easy as adding one line of CSS to it:

.element {shape-outside: circle(); /* content will flow around the circle defined on the element */}

Or:

.element {shape-outside: url(path/to/image-with-shape.png);}

But…

If you apply that line of CSS to your element, the shape won’t be applied to it unless two conditions are met:

  1. The element must be floated. Future levels of CSS Shapes may allow us to define shapes on non-floated elements, but not yet.
  2. The element must have intrinsic dimensions. The height and width set on an element will be used to establish a coordinate system on that element.

As you have seen in the function definitions above, the shapes are defined by sets of points. Because these points have coordinates, a coordinate system is necessary for the browser to know where to position each point on the element. So, the above example would work if it included something like:

.element {float: left;height: 10em;width: 15em;shape-outside: circle();}

Giving an element intrinsic dimensions does not, however, affect its responsiveness (we’ll talk more about that later).

Since each shape is defined by a set of points positioned using a pair of coordinates, changing the coordinates of a point will directly affect the shape created. For example, the following image shows a hexagonal shape that can be created using thepolygon() function. The shape is made up of six points. Changing the horizontal coordinate of the point in orange will change the resulting shape, and will affect the flow of content inside and/or outside any element this shape is applied to.

Image showing the result of changing the coordinate of a point on the created shape.
If the element is floated to the right and has this shape applied to it, the content on its left will change its flow when the coordinate of the orange point is changed inside thepolygon() function.

A Shape’s reference box#section4

CSS Shapes are defined and created inside areference box, which is the box used to draw the shape on the element. In addition to the element’s height and width, the element’s box model boxes—margin box,content box,padding box, andborder box—are also used as a reference to specify the extent of the shape on an element.

By default, the margin box is used as a reference—so, if an element you want to apply a shape to has a margin at the bottom, the shape you define on the element will extend to the edges of the margin area, not the element’s border area. If you want to use one of the other box values, you can specify it in conjunction with the shape function that you pass to the shape properties:

shape-outside: circle(250px at 50% 50%) padding-box;

Thepadding-box keyword in the above rule specifies that the shape is going to be applied and restricted to the padding box (padding area) of the element. Thecircle() function defines a circular shape, its size, and position on the element.

Defining Shapes using shape functions#section5

We’ll start by wrapping some information around a circular user avatar picture, like you might use to display a user profile or a testimonial.

Screenshot showing a user profile picture with text flowing around its circular boundaries.
Using CSS Shapes, text around a circular user profile image wraps to the shape, instead of staying rectangular.

We’ll use thecircle() function to apply a circular shape to the profile image, using the following markup:

<img src="http://api.randomuser.me/0.3.2/portraits/men/7.jpg" alt="profile image" /><p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Harum itaque nam blanditiis eveniet enim eligendi quae adipisci?</p><p>Assumenda blanditiis voluptas tempore porro quibusdam beatae deleniti quod asperiores sapiente dolorem error! Quo nam quasi soluta reprehenderit laudantium optio ipsam ducimus consequatur enim fuga quibusdam mollitia nesciunt modi.</p>

You might ask, “Why not useborder-radius to round the image?” The answer is that theborder-radius property has no effect on the flow of the content inside or around the element it’s applied to—it does not affect the content area of the element, or the flow area of the content around the element. It only affects the borders of an element, and any backgrounds. The background area is clipped to the curved corners created by the property, but that’s it. The content inside the element will remain rectangular, and the content outside the element will still see and treat the element as if it were rectangular—because it is.

Weare going to use theborder-radius property to make the image circular—this is what we usually do to round images or other elements on a page:

img {float: left;width: 150px;height: 150px;border-radius: 50%;margin-right: 15px;}
Screenshot showing how text would normally flow around an image without applying a CSS Shape to it.
Without CSS Shapes, the text sees the image as rectangular, and hence wraps around a rectangular shape, not a circular one.

In a browser that does not support CSS Shapes, the content around the circular image will flow around it as if it weren’t circular. This will be how the fallback will look in older browsers.

In order to change the flow of content to accommodate a certain shape, you use the shape properties.

img {float: left;width: 150px;height: 150px;border-radius: 50%;shape-outside: circle();shape-margin: 15px;}

With this code, the text will “see” the circular shape applied to the image and wrap around it, as shown in the first screenshot. (You can see the result livehere.) In non-supporting browsers it will fall back to the result shown in the second image.

You can use thecircle() function as is, or by passing parameters to it. Its official syntax is:

circle() = circle( [<shape-radius>]? [at <position>]? )

The question marks indicate that these parameters are optional and can be omitted. If you omit one, that parameter is set to its default value by the browser. When you usecircle() as is instead of explicitly setting its position, it will default to defining a circle that is positioned at the center of the element you’re applying it to.

You can specify the radius of the circle using any length unit (px,em,pt, etc.). You can also specify the radius using eitherclosest-side orfurthest-side, butclosest-side is the default, which means the browser will use the length from the center of the element to its closest side as the length of the radius.farthest-side uses the length from the center to the farthest side.

shape-outside: circle(farthest-side at 25% 25%); /* defines a circle whose radius is half the length of the longest side, positioned at the point of coordinates 25% 25% on the element’s coordinate system*/shape-inside: circle(250px at 500px 300px); /* defines a circle whose center is positioned at 500px horizontally and 300px vertically, with a radius of 250px */
Illustration showing a visual explanation of the closest-side and farthest-side values.

Theellipse() function works the same way as thecircle() function, with the same list of values, except that instead of taking one radius parameter, it takes two: one for the length of the radius on the x-axis, and another for the y-axis.

ellipse() = ellipse( [<shape-radius>{2}]? [at <position>]? )

While not directly related to a circle or an ellipse, theinset() function is used to create rectangular shapes inside an element. Since elements are already rectangular, though, we don’t need it to make more rectangles. Instead,inset() can help us create rectangles with rounded corners that also have content flow around those corners.

Image showing text flow around an element with and without the inset() function applied to it.

Theinset() function takes one to four offset values, which specify the offsets from the edges of thereferences box inward. These specify where the inset rectangle goes inside the element. The function also takes an optional parameter to round the corners of the inset rectangle. The rounded corners are specified exactly the same way asborder-radius, using one to four values, in conjunction with the keywordround.

inset() = inset( offset{1,4} [round <border-radius>]? )

The following will create a rounded rectangle on a floated element.

.element {float: left;width: 250px;height: 150px;shape-outside: inset(0px round 100px) border-box;}

Check the live example outhere.

The last Shape function is thepolygon(), which defines more complex arbitrary shapes using any number of points. The function takes in a set of coordinate pairs, each pair specifying the position of a point. The set of points make up the shape.

In the following example, an image floated to the right takes up the entire height of the screen using viewport units. We want to flow the text on the left around the hourglass inside the image, so we use thepolygon() function to define an irregular shape on the image.

Screenshot showing the result of applying the polygon() function to define a shape on an image and have content wrap around that shape.

The CSS for the above image looks like this:

img.right {float: right;height: 100vh;width: calc(100vh + 100vh/4);shape-outside: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);}

You can set the coordinates of the points defining the shape in length units or percentages, as I have here.

This code alone will produce the the above result, but as you can see, the shape function does not affect the remaining parts of the image outside the defined shape. As a matter of fact, applying a shape function to an element—whether an image, a container, or something in between—will not affect anything except the content flow area. Backgrounds, borders, and everything else remain unchanged.

In order to visualize the shape of the polygon we created, we need to “clip out” the parts of the image outside the shape. This is where theclip-path property from theCSS Masking Module can help.

Theclip-path property takes the same shape functions and values as the shape properties. If we pass the same polygonal shape we used in theshape-outside property to theclip-path property, it will clip all the parts of the image that are outside the defined shape.

img.right {float: right;height: 100vh;width: calc(100vh + 100vh/4);shape-outside: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);/* clip the image to the defined shape */clip-path: polygon(40% 0, 100% 0, 100% 100%, 40% 100%, 45% 60%, 45% 40%);}

The result looks like this:

Screenshot showing the result of applying the clip-path property to a shaped element to clip out excess parts of the image outside the defined shape.

Theclip-path property is supportedwith prefixes at this time, so it will work in Chrome with the-webkit- prefix added to theclip-path property. You can check the live demo outhere.

Theclip-path property is an excellent companion to the shape properties, as it helps visualize the created shapes and clip out any parts of the element that are outside the defined shapes, so you will probably find yourself using it a lot in conjunction with the Shapes properties.

Thepolygon() function also takes in an optional fill keyword, which can be eithernonzero orevenodd. This specifies how to treat areas inside the polygonal shape that may intersect itself. See theSVG fill-rule property for details.

Defining a shape using an image#section6

To define a shape using an image, the image needs an alpha channel from which the browser can extract the shape.

A shape is defined by the pixels whose alpha value is greater than a certain threshold. That threshold defaults to a value of 0.0 (fully transparent), or you can set it explicitly using theshape-image-threshold property. So, any pixel that is not transparent will be used as part of the shape defined from the image.

A future level of CSS Shapes may define a switch to use the luminance data from an image instead of the alpha data. If this happens,shape-image-threshold will be extended to apply its threshold to either alpha or luminance, depending on the switch state.

We’re going to use the following image to define a shape on an element and have text wrap around it:

Using theshape-outside property with theurl() value pointing to this image, we can flow the content around an element with this leaf shape.

.leaf-shaped-element {float: left;width: 400px;height: 400px;shape-outside: url(leaf.png);shape-margin: 15px;shape-image-threshold: 0.5;background: #009966 url(path/to/background-image.jpg);mask-image: url(leaf.png);}

Of course, if you were to apply a background to the element, the background would need to be clipped outside the defined shape. Themask-image property (with appropriate prefixes) from the Masking Module can do that, since theclip-path property doesn’t take an alpha image as a value. The result looks like this:

Screenshot showing text wrapped around a shape extracted from an image with an alpha channel.

If you’re creating complex shapes, you might want to define a shape using an image. This allows you to use an alpha channel image in Photoshop instead of manually defining the points.

You will also want to use an image instead of a shape function when you have multiple float or exclusion areas inside an element—because you can’t, for now, declare multiple shapes on an element. But if the image contains multiple areas, the browser will extract these areas from the image and use them.

CSS Shapes in responsive design#section7

Can CSS Shapes fit into our responsive workflows? The current specification forshape-outside has this covered, because it allows you to specify the dimensions of the element in either percentages or other length units, and the points defining the shape (parameters of the shape functions) can also be set in percentages. This means that an element with ashape-outside would be fully responsive, just like any other float with percentage dimensions.

shape-inside is not as responsive yet, but that’s because it has been pushed to Module Level 2. Many of its current limitations will be resolved in the next level.

Shape tools#section8

Creating complex shapes using Shapes functions can be a daunting task, especially if you’re creating one with many points and coordinates usingpolygon(). Thankfully, Adobe’s web platform team has been working on interactive tooling that makes this much easier. Bear Travis has createda collection of Shape Tools that allow us to create polygonal shapes visually. The tool then generates the shape function for us. This is useful, but it can be limited if you want to create a shape based on a specific image, because there is no way for you to insert the image into the tool and then create the shape for it.

A more advanced and interactive Shapes tool has been developed by the Adobe Web Platform team. The tool has beenrecently released as an extension for Adobe’s freeBrackets editor. It allows you to visualize and edit shapes directly in the browser, and has a live preview feature that updates the shape values in the stylesheet as you change them on the page. This gives you instant visual feedback for your changes, allowing you to see how your shapes interact with other elements on the page.

Screen capture showing how the new Shapes Editor can be used to edit Shapes right in the browser.
Editing a polygonal shape right in the browser using Brackets’ live preview mode.Screen capture courtesy of Razvan Caliman.

This tool will be indispensable because it facilitates creating, editing, and debugging our shapes. Razvan Caliman has writtenan article on the Brackets blog explaining how you can get the Shapes editor in Brackets and start using it today.

The future: CSS Exclusions#section9

The CSS Shapes specification used to be the CSS Shapes and Exclusions spec, but the two specs were separated. While CSS Shapes defines theshape-inside andshape-outside properties, CSS Exclusions will define properties that allow us to wrap content around elements that are not floated, such as absolutely positioned elements. This will make it possible to make content wrap the entire shape from different sides, as shown in the following image.

Screenshot of a magazine layout with text wrapped around a pullquote.
In the future, CSS Exclusions will allow us to wrap text around a shape like a pullquote, as shown in this magazine layout. The pullquote can also be circular, and the text would wrap around it just as well.Image byJustin Thomas Kay.

Similar layouts with shaped elements positioned absolutely at the center of an article—with text flowing around the element on all sides—will also be possible.

Taking Shapes further#section10

The current CSS Shapes specification is merely the first step. Soon, new options will give us more control over creating shapes and wrapping content in and around them, making it a lot easier for us to turn our mockups into live designs with just a few lines of code. Today, spec editors are focused on shippingshape-outside, and you’ll likely see CSS Shapes in more browsers by the end of 2014.

You can use Shapes today as part of a progressive enhancement workflow, knowing they have acceptable fallbacks in non-supporting browsers. I’ve recently started applying them tomy own website, and the fallback is very “normal.” For more complex designs, you can use a script to check whether a browser supports Shapes, and provide any fallback you want if it doesn’t. You can also extendModernizr’s tests withthis script to test whethershape-outside is supported, or download a custom build including this test.

CSS Shapes allow us to bridge one more gap between print and web design. The examples in this article are simple, but should give you a foundation for creating designs as complex as any magazine or poster—without having to worry whether you’ll be able to recreate it on-screen. Whatever you explore—fromnon-rectangular layouts toanimating Shapes—the time to experiment is now.

Recently by Sara Soueidan

Moving Forward with CSS Shapes

If you liked my CSS Shapes 101 article last week and are as excited about CSS Shapes as I am, then you may find a list of resources to dig deeper into CSS Shapes useful. In this post, I’m going to share with you some resources that can help you dig deeper into CSS Shapes that I’ve compiled (and written) over the time I’ve been working with Shapes.

Further reading aboutCode

Opportunities for AI in Accessibility

Microsoft's Accessibility Innovation Strategist discusses AI's potential for accessibility, emphasizing the need for responsible use and diverse teams to mitigate harm and promote inclusion for people with disabilities.

Mobile-First CSS: Is It Time for a Rethink?

Is mobile-first CSS always the best option? Patrick Clancey explores the pros and cons of the classic methodology, as well as when other solutions might work better.

58 Reader Comments

  1. Fantastic article Sara. Totally implies that CSS Shapes are going to shape the future web. 🙂

  2. Nice article Sara, CSS Shapes are just something so helpful and beautiful in the browser. Now is time for some experiments.

  3. Great article – lots of potential with shapes. One thing I disagree with though is suggesting people use Brackets…on a Mac it’s crap – always crashing. Gave up on it last year.

  4. Spectacular read. Very insightful and full of actionable items. One thing to always keep in mind – “responsive” and “mobile friendly” are not the same thing. This is why Google created the mobile friendly testing tool.SEO received a big shakeup when the search results changed due to mobile.

    At the end of the day, design should never be taken lightly. This is an excellent explanation.

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

“Successful” or “Unsuccessful”: the Post-“Good Design” Vocabulary

Business

Design for Amiability: Lessons from Vienna

Computing was born in a Viennese café. Between 1928 and 1934, while Hitler plotted and Europe crumbled, a motley crew of mathematicians, philosophers, architects, and economists gathered weekly to puzzle out the limits of reason—and invented Computer Science in the process. What made their collaboration possible wasn't just brilliance (though they had plenty). It was amiability: the careful design of a social space where difficult people could disagree without destroying each other. Longtime A List Apart contributing author Mark Bernstein mines this forgotten history for lessons that might just save today's embattled web from its worst impulses. Spoiler: it involves better coffee service and the looming threat of public humiliation.

Design Dialects: Breaking the Rules, Not the System

Design systems aren't component libraries—they’re living languages. Rigid adherence to visual rules creates brittle systems that break under contextual pressure. Fluent systems bend without breaking.
Design

An Holistic Framework for Shared Design Leadership

Having both a Design Manager and a Lead Designer on the same team is beautiful, but can be messy. To make it work without creating confusion, overlap, or “too many cooks,” check Michel Ferreira’s Holistic Framework for Shared Design Leadership.

From Beta to Bedrock: Build Products that Stick.

Building towards bedrock means sacrificing some short-term growth potential in favour of long-term stability. But the payoff is worth it: products built with a focus on bedrock will outlast and outperform their competitors, and deliver sustained value to users over time. Liam Nugent shows us how.
Northwestern Information Design and Strategy, School Of Professional Studies

Build advanced skills for growing career opportunities. Choose from tracks in content strategy, UX/UI, communication with data, and learning design.


[8]ページ先頭

©2009-2026 Movatter.jp