Adobe

decor

Web Platform Team Blog

Making the web awesome

Freeing the Floats of the Future From the Tyranny of the Rectangle

Note: CSS Shapes syntax has changed. For the latest information, see CSS Shapes Module Level 1.

With modern web layout you can have your content laid out in whatever shape you want as long as it’s a rectangle. Designers in other media have long been able to have text and other content lay out inside and around arbitrarily complex shapes. The CSS Exclusions, CSS Shapes Level 1, and CSS Shapes Level 2 specifications aim to bring this capability to the web.

While these features aren’t widely available yet, implementation is progressing and it’s already possible to try out some of the features yourself. Internet Explorer 10 has an implementation of the exclusions processing model, so you can try out exclusions in IE 10 today.

At Adobe we have been focusing on implementing the shapes specification. We began with an implementation of shape-inside and now have a working implementation of the shape-outside property on floats. We have been building our implementation in WebKit, so the easiest way to try it out yourself is to download a copy of Chrome Canary. Once you have Canary, enable Experimental Web Platform Features and go wild!

What is shape-outside?

“Now hold up there,” you may be thinking, “I don’t even know what a shape-outside is and you want me to read this crazy incomprehensible specification thing to know what it is!?!”

Well you’ll be happy to know that it really isn’t that complex, especially in the case of floats. When an element is floated, inline content avoids the floated element. Content flows around the margin box of the element as defined by the CSS box model. The shape-outside CSS property allows you to tell the browser to use a specified shape instead of the margin box when wrapping content around the floating element.

CSS Exclusions

The current implementation allows for rectangles, rounded rectangles, circles, ellipses, and polygons. While this gives a lot of flexibility, eventually you will be able to use a SVG path or the alpha channel of an image to make it easier to create complex shapes.

How do I use it?

First, you need to get a copy of Chrome Canary and then enable Experimental Web Platform features. Once you have that, load up this post in Chrome Canary so that you can click on the images below to see a live example of the code. Even better, the examples are on Codepen, so you can and should play with them yourself and see what interesting things you can come up with.

Note that in this post and the examples I use the unprefixed shape-outside property.
If you want to test these examples outside of my Codepen then you will need to use the prefixed -webkit-shape-outside property or use (which is a built in option in Codepen).

We’ll start with a HTML document with some content and a float. Currently shape-outside only works on floating elements, so those are the ones to concentrate on. For example: (click on the image to see the code)

HTML without shape-outside

You can now add the shape-outside property to the style for your floats.

.float {
  shape-outside: circle(50%, 50%, 50%);
}

A circle is much more interesting than a standard rectangle, don’t you think? This circle is centered in the middle of the float and has a radius that is half the width of the float. The effect on the layout is something like this:

shape-outside circle

While percentages were used for this circle, you can use any CSS unit you like to specify the shape. All of the relative units are relative to the dimensions of element where the shape-outside is specified.

Supported shapes

Circles are cool and all, but I promised you other shapes, and I will deliver. There are four types of shapes that are supported by the current shape-outside implementation: rectangle, circle, ellipse, and polygon.

rectangle

You have the ability to specify a shape-outside that is a fairly standard rectangle:

shape-outside: rectangle(x, y, width, height);

The x and y parameters specify the coordinates of the top-left corner of the rectangle. This coordinate is in relation to the top-left corner of the floating element’s content box. Because of the way this interacts with the rules of float positioning, setting these to anything other than 0 causes an effect that is similar to relatively positioning the float’s content. (Explaining this is beyond the scope of this post.)

The width and height parameters should be self-explanatory: they are the width and height of the resulting rectangle.

Where things get interesting is with the six-argument form of rectangle:

shape-outside: rectangle(x, y, width, height, rx, ry);

The first four arguments are the same as explained above, but the last two specify corner radii in the horizontal (rx) and vertical (ry) directions. This not only allows the creation of rounded rectangles, you can create circles and ellipses as well. (Just like with [border-radius][border-radius].)

Here’s an example of a rectangle, a rounded rectangle, a circle, and an ellipse using just rectangle syntax:

shape-outside rectangle

If you’re reading this in Chrome Canary with exclusions turned on, play around with this demo and see what other things you can do with the rectangles.

circle

I already showed you a simple circle demo and you’ll be happy to know that’s pretty much all there is to know about circles:

shape-outside: circle(cx, cy, radius);

The cx and cy parameters specify the coordinates of the center of the circle. In most situations you’ll want to put them at the center of your box. Just like with rectangles moving this around can be useful, but it behaves similarly to relatively positioning the float’s content with respect to the shape.

The radius parameter is the radius of the resulting circle.

In case you’d like to see it again, here’s what a circle looks like:

shape-outside circle

While it is possible to create circles with rounded rectangles as described above, having a dedicated circle shape is much more convenient.

ellipse

Sometimes, you need to squish your circles and that’s where the ellipse comes in handy.

shape-outside: ellipse(cx, cy, rx, ry);

Just like a circle, an ellipse has cx and cy to specify the coordinates of its center and you will likely want to have them at the center of your float. And just like all the previous shapes, changing these around will cause the float’s content to position relative to your shape.

The rx and ry parameters will look familiar from the rounded rectangle case and they are exactly what you would expect: the horizontal and vertical radii of the ellipse.

Ellipses can be used to create circles (rx = ry) and rounded rectangles can be used to create ellipses, but it’s best to use the shape that directly suits your purpose. It’s much easier to read and maintain that way.

Here’s an example of using an ellipse shape:

shape-outside ellipse

polygon

Now here’s where things get really interesting. The polygon `shape-outside` allows you to specify an arbitrary polygonal shape for your float:

shape-outside: polygon(x1 y1, x2 y2, ... , xn yn);

The parameters of the polygon are the x and y coordinates of each vertex of the shape. You can have as many vertices as you would like.

Here’s an example of a simple polygon:

shape-outside triangle

Feel free to play with this and see what happens if you create more interesting shapes!

Putting content in the float

The previous examples all had divs without any content just to make it easier to read and understand the code, but a big motivation for shape-outside is to wrap around other content. Interesting layouts often involve wrapping text around images as this final example shows:

shape-outside with images

As usual, you should take a look and play with the code for this example of text wrapping around floated images. This is just the beginning of the possibilities, as you can put a shape outside on any floating element with any content you want inside.

Next steps

We are still hard at work on fixing bugs in the current implementation and implementing the rest of the features in the CSS Shapes Level 1 specification. We welcome your feedback on what is already implemented and also on the spec itself. If you are interested in becoming part of the process, you can raise issues with the current WebKit implementation by filing bugs in the WebKit bugzilla. If you have issues with the spec, those are best raised on the www-style mailing list. And of course, you can leave your feedback as comments on this post.

I hope that you enjoy experimenting with shape-outside and the other features we are currently working on.

12 Comments

  1. March 27, 2013 at 3:01 pm, Martin Hlaváč said:

    Keep up the good work. These new floats look just gorgeously. I am looking forward to play with them.

    Is there any way how to make similiar thing on older browsers? SVG maybe? I am just interested as this would be useful in making magazine like pages, or in rendering magazines directly in web browser.

    It would be nice to have some javascript implementation that could make this available for majority of browsers that are currently available and used.

    • March 27, 2013 at 3:08 pm, Bem Jones-Bey said:

      Glad you like it.

      The polyfill I’ve seen only works with images, and is here: http://www.jwf.us/projects/jQSlickWrap/
      (It’s based off the technique explained in this list apart article: http://alistapart.com/article/sandbags)

      If you want to put other content in your floats and wrap around them, I’m not sure if it’s possible to do that in a nice general way like the jQSlickWrap polyfill does.

  2. March 29, 2013 at 2:08 pm, CSS Exclusions and Shapes is moving forward | Mihai Corlan said:

    [...] might also want to read this post. If you want to send us your feedback, please do it. For bugs use this [...]

  3. April 05, 2013 at 10:05 am, Vincent De Oliveira said:

    Hi.
    I went into a problem with the shape-outside property that didn’t seem to work as the *old* wrap-shape property does:
    – The exclusion only apply to the first part when the content is flowed into multiples parts (like Multicolumn or Regions).
    – For now, it’s only for float, while the old one used to work with all positioned content

    Can you explain the reason?

    Vincent

    • April 05, 2013 at 10:40 am, Bem Jones-Bey said:

      - The exclusion only apply to the first part when the content is flowed into multiples parts (like Multicolumn or Regions).

      Can you show me an example of this? I’m not sure what you mean.

      - For now, it’s only for float, while the old one used to work with all positioned content

      We decided to start with floats for the actual implementation. The implementation with support for wrap-shape was a prototype implementation. Having it work on all positioned content (with the wrap-flow property) is something that we will be working on. Note that IE 10 implements the wrap-flow property now if you want to play with it, but they don’t yet implement shapes.

  4. April 06, 2013 at 7:05 am, Vincent De Oliveira said:

    Thank you for your reply.

    I made a CodePen here: http://codepen.io/iamvdo/pen/HoGtu

    I’m just answering you because i found old samples made by Adobe that used to work with polygon on all positioned content, even if the content is flowed into multiple parts. (The Bonneville Speedway Panorama demo here: http://stlab.adobe.com:8080/@rev1=head@//compliance/css-regions-v01/samples/viewer.html?url=advanced_panorama.html)

    Vincent.

    • April 08, 2013 at 2:40 pm, Bem Jones-Bey said:

      I made a CodePen here: http://codepen.io/iamvdo/pen/HoGtu

      Ah, now I see what you’re trying to do. The problem is that the float is contained within the column, and there is no way for it to spill out of the column and affect the content in the next one. A shape outside on a float can only affect content that an ordinary float could affect. In order to do what you want, you do need the full exclusions model with the wrap-flow property, but we haven’t implemented that in WebKit yet.

      I’m just answering you because i found old samples made by Adobe that used to work with polygon on all positioned content, even if the content is flowed into multiple parts. (The Bonneville Speedway Panorama demo here: http://stlab.adobe.com:8080/@rev1=head@//compliance/css-regions-v01/samples/viewer.html?url=advanced_panorama.html)

      Yeah, we had an old prototype build that had these features; however, it was just a prototype. It wasn’t anywhere near something that could be shipped in a real browser. What we are working on now is the full implementation, which is considerably more involved. So unfortunately, unless you use the old prototype build, you can’t do that yet.

  5. April 30, 2013 at 5:33 am, Facebook Chatheads in CSS | TerrenceRyan.com said:

    [...] a few weeks ago a colleague of mine at Adobe, Bem Jones-Bey wrote an article about using shaped exclusions from the CSS Shapes and Exclusion spec.  It seemed like a perfect fit.  So if you have Chrome Canary installed, and the experimental [...]

  6. June 19, 2013 at 11:29 am, Web Platform Wednesday, Week 7: More text properties and exclusions | Web Platform Blog said:

    [...] There are some great explanations of CSS Exclusions out there, such as Hans Muller’s Growing and Shrinking Polygons: Round One and Bem Jones-Bey’s Freeing the Floats of the Future From the Tyranny of the Rectangle. [...]

  7. August 12, 2013 at 5:32 am, The CSS Shapes Module — Breaking Out of the Box - Vanseo Design said:

    […] is closer to being production ready to talk about it here. However, this spec has the potential to completely free us from always having to use rectangles and that possibility should excite […]

  8. August 23, 2013 at 1:53 am, Mats said:

    Could this be applied to a flex layout as well?
    Imagine a flex layout with a menu (flex: 0 1 auto) to the left that has the shape of a circle (or ellipse) and the content of the site to the right (flex: 1 1 auto) flowing around the circle (or ellipse), centered vertically.
    To make it look exactly like the first in this article. :)

    • August 23, 2013 at 9:35 am, Bem Jones-Bey said:

      You can only apply shapes to floats at the moment. And each flex item creates a new block formatting context, so a float in one flex item cannot affect the flow in another flex item. In order to do what you want, you’d need the full CSS Exclusions model, which we haven’t yet implemented. But when it does get implemented, you will be able to do just that and more.

      Note that since this article was written, the CSS Exclusions and Shapes specification has been split into multiple specifications, CSS Exclusions, CSS Shapes Level 1, and CSS Shapes Level 2.