Copyright © 2011 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
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.
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.
wrap-shape-mode’
property
wrap-shape-order’
property
wrap-shape’
property
wrap-shape-image’
property
wrap-shape-image-threshold’ property
wrap-shape-margin’, ‘wrap-shape-padding’ properties
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".
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’
wrap-shape-margin’
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.
wrap-shape-mode’ propertyBy 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 |
wrap-shape-mode’ to ‘none’ will disable both the exclusion shape
and the content shape.
|
|
|
|
|
|
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>

The #circle DIV's shape is used as an exclusion for the region with content. Note: mycircle.png has a solid fill
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).
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.
wrap-shape-order’ propertyExclusions 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:
wrap-shape-order’ is set to 0. The
element does not establish a new wrapping context, unless it is a root
element.
wrap-shape’ propertyExclusion 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.
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.
If the polygon is not closed the user-agent will automatically add a new vertex at the end.
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.
wrap-shape-image’ propertyOne 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 |
wrap-shape-image-threshold’ propertyDefines 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 |
‘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’.
wrap-shape-margin’, ‘wrap-shape-padding’ propertiesBecause 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>
| 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 |
| 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 |
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.
| 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 |