W3C

CSS Exclusions Module

Editor's Draft 4 May 2011

This version:
http://www.w3.org/csswg/css3-exclusions
Latest version:
http://www.w3.org/csswg/css3-exclusions
Previous version:
none
Editors:
Vincent Hardy, Adobe Systems, Inc.,
Authors and Former Editors:
Stephen Zilles, Adobe Systems, Inc.,
Alexandru Chiculita, Adobe Systems, Inc.,
Andrei Bucur, Adobe Systems, Inc.,
Mihnea Ovidenie, Adobe Systems, Inc.,
Peter Sorotokin, Adobe Systems, Inc.,
Virgil Palanciuc, Adobe Systems, Inc.,
Arno Gourdol, Adobe Systems, Inc.,

Abstract

CSS Exclusions extend the concept of CSS floats (see [CSS21]): they provide the ability to exclude arbitrary areas around which content can flow. CSS Exclusions also allow content to flow in these exclusions areas. CSS Exclusions enable sophisticated layouts, for example having content flow into and/or around circles or other, arbitrarily complex shapes.

Status of this document

This is a public copy of the editors' draft. It is provided for discussion only and may change at any moment. Its publication here does not imply endorsement of its contents by W3C. Don't cite this document other than as work in progress.

The (archived) public mailing list www-style@w3.org (see instructions) is preferred for discussion of this specification. When sending e-mail, please put the text “css3-exclusions” in the subject, preferably like this: “[css3-exclusions] …summary of comment…

This document was produced by the CSS Working Group (part of the Style Activity).

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Table of contents

1. Introduction

The sections below define features that allow text to wrap around and inside non-rectangular shapes. The term "exclusion shape" refers to the exterior of the shape and the term "content shape" refers to the interior of the shape. The text will wrap around the "exclusion shape" and will wrap inside the "content shape".

2. Background

This section is not normative.

Exclusions are arbitrary shapes that will be avoided by the user agent when laying out content. The exclusion shape of an element is generated from the element's ‘wrap-shape’ property. The exclusion area is computed relative to the content box of the element on which the exclusion is specified.

Elements that specify ‘wrap-shape-mode’ different than ‘none’ setup a wrapping context for all the child elements.

Note: Elements that have no wrapping context are not affected by any exclusion.

Exclusion shapes affect only the content outside the element on which the exclusion was defined. In other words, exclusion shapes do not affect the element's children.

The ‘wrap-shape-mode’ property is used to enable the definition of exclusion shape. Setting ‘wrap-shape-mode’ to something other than ‘none’ will affect both exterior and interior element's content. It will make all the elements outside wrap around the shape defined by ‘wrap-shape’. Moreover, the children elements will wrap inside the specified shape.


There are two other properties that can be used in conjunction with the ‘wrap-shape’:

wrap-shape-padding
contracts the boundary of the wrap shape to obtain a content shape
wrap-shape-margin
expands the boundary of the wrap shape to obtain an exclusion shape

By default, the shape is defined by the content box of the element. The content shape will be intersected with the exclusion shape at the content-block coordinate space using exclusion shape projections. If multiple parent elements define content shapes, only the nearest one in the DOM tree is used to calculate the wrapping area inside which the element is laid out.

Another property, ‘wrap-shape-order’, describes the layer at which the exclusion works. An exclusion can affect all the elements in the same exclusion context with the ‘wrap-shape-order’ smaller or equal than its ‘wrap-shape-order’.

The ‘wrap-shape-order’ property was necessary to describe a sort of grouping between the elements affected by exclusion shapes. We wanted to avoid overloading the meaning of ‘z-index’ property (which is available only for elements with ‘position’ property set) and also we wanted something more than just the DOM order.

The ‘wrap-shape-order’ property does not influence the positioning of DOM elements.

When laying out content, the user agent will compute a dependency graph for DOM elements that will take wrap shapes into account. The dependency graph will be computed based on the values of ‘wrap-shape-order’ property. For elements with equal ‘wrap-shape-order’ values, dependency is computed based on the order of the elements in DOM.

2.1. Properties

2.1.1. The ‘wrap-shape-mode’ property

By default, the property has the value ‘none’ and the engine will not use the element as an text-wrapping exclusions for other elements. Setting the property to ‘around’, ‘left’, ‘right’, ‘maximum’ or ‘top-bottom’ will enable the exclusion text-wrapping features and the wrapping mode for the outside content. The element's inside content will always fill the content shape.

The element will be considered an exclusion shape for anything outside the element and a content shape for everything inside that element. By ‘outside’ we mean the elements in DOM that are not children of the element on which the wrap shape was defined and have a wrapping context. By ‘inside’ we mean the children of the element on which the wrap shape was defined. The default shape is the content box as defined by the CSS box model.

When the property is set to ‘content’ only the elements inside the element will wrap inside the content shape. The ‘content’ value is used to disable the exclusion shape while still keeping the content shape enabled.

The content shape does not affect the element's children with ‘position’ = fixed or absolute (and the children of those elements).

Name: wrap-shape-mode
Value: none | around | left | right | maximum | top-bottom | content
Initial: none
Applies to: any block element
Inherited: no
Percentages: N/A
Media: visual
Computed value: as specified
Example rendering for wrap-shape-mode: around Example rendering for wrap-shape-mode: content
Example rendering for wrap-shape-mode: left Example rendering for wrap-shape-mode: right
Example rendering for wrap-shape-mode: maximum Example rendering for wrap-shape-mode: top-bottom

Define a circle as an exclusion shape. The center of the circle shape is computed as follows: cx = 50% from the div width, cy = 50% from the div height. The div has the id = "circle" and the center of the circle is calculated percent from the div box dimensions. The radius cannot be specified as percent, therefore is specified in units.

                        <style>
                        #circle {
                          wrap-shape: circle(50%, 50%, 30px);
                          wrap-shape-margin: 10px;
                        }
                        </style>

                        <div id="circle">
                        <img src="mycircle.png"/>
                        </div>
                        <div>Lorem ipsum</div>

It might be easier to just use the original image alpha channel to define the exclusion shape.

                        <style>
                        #circle {
                          background: url(mycircle.png);
                          wrap-shape-image: url(mycircle.png);
                          wrap-shape-margin: 10px;
                        }
                        </style>

                        <div id="circle"></div>
                        <div>Lorem ipsum</div>

Text wrapping around a circle

The #circle DIV's shape is used as an exclusion for the region with content. Note: mycircle.png has a solid fill

2.1.1.1. Combining exclusions

There are cases when multiple exclusions with different ‘left’ or ‘right’ modes will overlap the same text lines. In that case the rules will still apply, meaning that overlapping lines will be skipped (see the image below for more details).

Combining exclusions with left and right wrap modes

We thought about defining a value ‘exclusion’ (‘no-content’) for the ‘wrap-shape-mode’ property. Such value would make the wrap shape as exclusion only, as opposed to content. However, we were unable to find a compelling reason/use case for such a value.

This section on grouping exclusions or describing their interactions needs to be further detailed.

2.1.2. The ‘wrap-shape-order’ property

Exclusions will only affect the block elements with equal or smaller ‘wrap-shape-order’ value in the same wrapping context. The values can be both positive and negative. A ‘wrap-shape-order’ value other than auto, will establish a new wrapping context, in the same way ‘z-index’ non auto values establish a new stacking context.

The user agent will sort all the elements using the ‘wrap-shape-order’ property. The elements with a smaller order will wrap around the elements with bigger ‘wrap-shape-order’. Elements with equal ‘wrap-shape-order’ values will be sorted using the order in the source DOM.

When the ‘wrap-shape-order’ is set to auto, the ‘wrap-shape-order’ is set to 0.

Name: wrap-shape-order
Value: <integer> | auto
Initial: auto
Applies to: any block element, exclusions
Inherited: no
Percentages: N/A
Media: visual
Computed value: as specified

Values have the following meaning:

2.1.3. The ‘wrap-shape’ property

Exclusion shape can get out of the content box of the element on which it is defined. In this case, the exclusion shape is not clipped to the margins of the

As opposed to the exclusion shape, the content shape will be clipped by the content-box rectangle.

Exclusion shape (and content shape) defined using a polygon

wrap-shape: polygon(x1, y1, …, xn, yn);
Name: wrap-shape
Value: <shape> | auto
Initial: auto
Applies to: any block element
Inherited: no
Percentages: relative to the element width or height
Media: visual
Computed value: the specified value

Shapes are used to describe the value of the ‘wrap-shape’ property. The ‘wrap-shape’ property is used to define the boundary in which to flow content and also used to define the area to be avoided when laying out content.

The shape can be defined using SVG style basic shapes as defined by the SVG Shapes.

auto
The wrap-shape will computed based on the content box of the element.
<shape>
A shape defined in the Computing the shapes section.
2.1.3.1. Computing the shapes

All the lengths can be expressed in percentages and are defined in the coordinate space of the element. Percentages will take into account the element width/height excluding any padding or margins. The (x,y) coordinates are relative to the block's content box.

When defining a polygon area using percentages, the content box of the element must always be fully known in advance.

rect(x, y, width, height, [[rx], ry])
circle(cx, cy, r)
ellipse(cx, cy, rx, ry)
polygon([fillRule], x1, y1 x2, y2 x3, y3 … xn, yn)

If the polygon is not closed the user-agent will automatically add a new vertex at the end.


path([fillRule], ...)

The content of the path() function will be parsed using SVG PathData notation.

                        <div id="circle" style="wrap-shape: circle(50%, 50%, 40px); width: 100px;
                        height: 100px;"></div>
                                        

In this example, the actual position of the exclusion shape polygon is determined based on the position of the "circle" div element.

2.1.4. Define exclusion using an image alpha channel: ‘wrap-shape-image’ property

One can define an exclusion by specifying a source image whose alpha channel is used to compute the exclusion shape. As image, one can specify the same values as the ones used when defining the values for the ‘background-image’ property.

The exclusion shape is computed to be the path that encloses the area where the opacity of the specified image is greater than the ‘wrap-shape-image-threshold’ value. If the ‘wrap-shape-image-threshold’ is not specified, the default value to be considered is 50%.

Note: Images can also define cavities and text should wrap inside them. In order to avoid that, another exclusion element can be overlaid.

Exclusion shape defined using the alpha channel of the specified image, opacity threshold 50%.

                        <style>
                        #id {
                                wrap-shape-image: url(myimage.png);
                        }
                        </style>
                                        
Name: wrap-shape-image
Value: none | <url>
Initial: none
Applies to: any block element
Inherited: no
Percentages: N/A
Media: visual
Computed value: the specified value

2.1.5. wrap-shape-image-threshold’ property

Defines the alpha channel threshold used to define the shape using an image. The default is 50%, meaning that all the pixels that are more than 50% transparent define the path of the exclusion shape.

Exclusion shape defined using the alpha channel of the specified image, opacity filter 75%.

                        <style>
                        #id {
                                wrap-shape-image: url(myimage.png);
                                wrap-shape-image-threshold: 75%;
                        }
                        </style>
                                        
Name: wrap-shape-image-threshold
Value: <percent>
Initial: 50%
Applies to: any block element
Inherited: no
Percentages: N/A
Media: visual
Computed value: the specified value

2.1.6. Other wrap-shape-image properties

wrap-shape-image-repeat’, ‘wrap-shape-image-attachment’, ‘wrap-shape-image-position’, ‘wrap-shape-image-size

These properties are equivalent to the ones available for the ‘background’ property as defined in CSS Background module . The properties apply only to the ‘wrap-shape-image’.

2.1.7. wrap-shape-margin’, ‘wrap-shape-padding’ properties

Because the ‘wrap-shape’ and ‘wrap-shape-image’ properties define a single shape for both the exclusion shape and the content shape, two new properties allow to distinguish between them even more using specified offsets: ‘wrap-shape-margin’ property can be used to offset the exclusion shape from the one specified with ‘wrap-shape’ or ‘wrap-shape-image’ properties. ‘wrap-shape-padding’ property can be used to offset the content shape from the one specified with ‘wrap-shape’ or ‘wrap-shape-image’ properties.

The exclusion shape is used to wrap elements that are not content of the specified block. The content shape is used to wrap the content elements.

Both margin and padding can take negative values. However, the content shape will be clipped by the content-box rectangle, so that interior elements will not be rendered outside the content-box of the block element.

Text wrapping around an irregular shape.

                        <style>
                        #div2 {
                                wrap-shape: poly(50px, 50px, 10px);
                                wrap-shape-margin: 10px;
                                wrap-shape-padding: 10px;
                        }
                        </style>
                                        

2.1.8. Affecting the exclusion shape

Name: wrap-shape-margin
Value: length
Initial: 0
Applies to: any block element
Inherited: no
Percentages: N/A
Media: visual
Computed value: the specified value

2.1.9. Affecting the content shape

Name: wrap-shape-padding
Value: length
Initial: 0
Applies to: any block element
Inherited: no
Percentages: N/A
Media: visual
Computed value: the specified value

Visual example for wrap-shape-padding and wrap-shape-margin

3. Q&A

1. Can the wrap-shape-margin and wrap-shape-padding be negative?
In the CSS box model only the margins can be negative. This is also applicable in the wrap-shape case to obtain a pull content effect for exclusions.

2. How is wrapping around concave shapes?
The text will be flowed around the concave shape and will fill all the available outer space.

3. All of the wrap-shape-mode values other than ‘none’ define a content shape for child elements, and while the different values (left, right, around) may affect how the exclusion shape interacts with other elements, they do not change how the content shape works. Correct?
Yes.

4. How does a content shape interact with non-text content?
The content shape does not affect elements with position absolute or fixed.

4.1 Does it clip an image?
No.

4.2 Does it clip the background-color and background-image?
No.

4.3 If there is a border defined does it draw around the content shape (plus wrap-shape-padding) boundary?
No.

5. I am assuming that a content shape (and perhaps the content itself) may determine an element’s height and width if they are not specified, but they do not override explicit height and width.
Yes, the content shape do not override explicit height and width. The content shape is clipped by the content-box margins.
When the content box of the element is not defined, the content shape cannot be defined using percentages. In this case, the content shape will determine the elements width and height.

6. The permissible wrap-shape-order property values should include “auto”.
This is correct. Wrap shape order is not an inherited property in the same way z-index is not inheritable.

7. The element will be considered an exclusion for anything outside the element and a content shape for everything inside that element.

7.1 Does "anything outside the element" include content that came before the element in DOM order?
Yes.

7.2 If I put a wrap on an element, and then cause it to be positioned *above* where it would normally go, will the text in the previous element wrap around it?
It depends.

Example 7.2.A:

<style>
    #div1 { }
    #div2 {
        wrap-shape-mode: left;
        wrap-shape: poly(...);
        position: absolute;
        top: 5px;
    }
</style>
<div id="div1">Text inside div1</div>
<div id="div2">Text inside div2</div>                                                

In this case, the second div, on which the wrap-shape is defined, is absolutely positioned. Because of that, the exclusion shape can be computed. The text inside the ‘div1’ will flow around the exclusion shape.

Example 7.2.B:

<style>
#div1 { }
#div2 {
      wrap-shape-mode: left;
      wrap-shape: poly(...);
}
=</style>
                        <div id="div1">Text inside div1</div>
                        <div id="div2">Text inside div2</div>
                                

In this case, both divs are statically positioned. The second div can be positioned only after the first div is positioned. Because of that, the wrap shape defined on the second div does not influence the text layout for the first div.

Example 7.2.C:

                        <style>
                                #div1 { }
                            #div2 {
                                    wrap-shape-mode: left;
                                    wrap-shape: poly(...);
                                    position: relative;
                                    top: -50px;
                            }
                        </style>
                        <div id="div1">Text inside div1</div>
                                <div id="div2">Text inside div2</div>
                                        

In this case, the second div is positioned after the first div is positioned. Therefore, the wrap shape cannot be computed so that it can be taken into account when the first div is laid out. Even if the divs will overlap, the wrap shape does not influence the layout of text from ‘div1’.

Example 7.2.D:

                        <style>
                                #div1 {
                                        wrap-shape-mode: right;
                                        wrap-shape: poly(...);
                                        position: absolute;
                                        top: 50px;
                                        left: 10px;
                                }
                                #div2 {
                                        wrap-shape-mode: left;
                                        wrap-shape: poly(...);
                                        position: absolute;
                                        top: 50px;
                                        left: 50px;
                                }
                        </style>
                        <div id="div1">Text inside div1</div>
                        <div id="div2">Text inside div2</div>
                                        

In this case, both divs are absolutely positioned. They both have the ‘wrap-shape-order’ equal to 0. Since the first div is the first one in DOM, it's ‘wrap-shape’ influences the layout of the second div. The second div ‘wrap-shape’ does not influence the layout of the first div.

8. In CSS2.1, content property cannot be inherited. In CSS3, content property might be inherited. Will content: flow(region_thread_name) be inherited?
No.

4. Conformance

Acknowledgments

References

Normative references

Other references

[CSS21]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 23 April 2009. W3C Candidate Recommendation. (Work in progress.) URL: http://www.w3.org/TR/2009/CR-CSS2-20090423

Index

Property index

 

Property Values Initial Applies to Inh. Percentages Media
wrap-shape <shape> | auto auto any block element no relative to the element width or height visual
wrap-shape-image none | <url> none any block element no N/A visual
wrap-shape-image-threshold <percent> 50% any block element no N/A visual
wrap-shape-margin length 0 any block element no N/A visual
wrap-shape-mode none | around | left | right | maximum | top-bottom | content none any block element no N/A visual
wrap-shape-order <integer> | auto auto any block element, exclusions no N/A visual
wrap-shape-padding length 0 any block element no N/A visual