shape-outside

The shape-outside CSS property uses shape values to define the float area for a float and will cause inline content to wrap around the shape instead of the float's bounding box.

/* Keyword values */
shape-outside: none;
shape-outside: margin-box;
shape-outside: content-box;
shape-outside: border-box;
shape-outside: padding-box;
/* Function values */
shape-outside: circle();
shape-outside: ellipse();
shape-outside: inset(10px 10px 10px 10px);
shape-outside: polygon(10px 10px, 20px 20px, 30px 30px);
/* <url> value */
shape-outside: url(image.png);
/* Gradient value */
shape-outside: linear-gradient(45deg, rgba(255, 255, 255, 0) 150px, red 150px);
/* Global values */
shape-outside: initial;
shape-outside: inherit;
shape-outside: unset;

Initial valuenone
Applies tofloats
Inheritedno
Mediavisual
Computed valueas defined for <basic-shape> (with <shape-box> following, if supplied), the <image> with its URI made absolute, otherwise as specified.
Animation typeyes, as specified for <basic-shape>, otherwise no
Canonical orderthe unique non-ambiguous order defined by the formal grammar

Syntax

Values

none
The float area is unaffected.
<shape-box>
If one of the values margin-box, border-box, padding-box or content-box is specified, the shape is computed based on it. The shape uses their respective box including curvature from border-radius, similar to background-clip.
<basic-shape>
The shape is computed based on the values of one of inset(), circle(), ellipse() or polygon(). If also a <shape-box> is supplied, this defines the reference box for the <basic-shape> function. If <shape-box> is not supplied, then the reference box defaults to margin-box.
<image>
The shape is extracted and computed based on the alpha channel of the specified <image> as defined by shape-image-threshold.
User agents must use the potentially CORS-enabled fetch method defined by the HTML5 specification for all URLs in a shape-outside value. When fetching, user agents must use "Anonymous" mode, set the referrer source to the stylesheet's URL and set the origin to the URL of the containing document. If this results in network errors such that there is no valid fallback image, the effect is as if the value 'none' had been specified.

Interpolation

For interpolating between one basic shape and a second, the rules below are applied. The values in the shape functions interpolate as a simple list. The list values interpolate as length, percentage, or calc where possible. If list values are not one of those types but are identical (such as finding nonzero in the same list position in both lists) those values do interpolate.

  • Both shapes must use the same reference box.
  • If both shapes are the same type, that type is ellipse() or circle(), and none of the radii use the closest-side or farthest-side keywords, interpolate between each value in the shape functions.
  • If both shapes are of type inset(), interpolate between each value in the shape functions.
  • If both shapes are of type polygon(), both polygons have the same number of vertices, and use the same <fill-rule>, interpolate between each value in the shape functions.
  • In all other cases no interpolation is specified.

Formal syntax

none | <shape-box> || <basic-shape> | <image>

where
<shape-box> = <box> | margin-box
<basic-shape> = <inset()> | <circle()> | <ellipse()> | <polygon()>
<image> = <url> | <image()> | <image-set()> | <element()> | <cross-fade()> | <gradient>

where
<box> = border-box | padding-box | content-box
<inset()> = inset( <length-percentage>{1,4} [ round <border-radius> ]? )
<circle()> = circle( [ <shape-radius> ]? [ at <position> ]? )
<ellipse()> = ellipse( [ <shape-radius>{2} ]? [ at <position> ]? )
<polygon()> = polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )
<image()> = image( [ [ <image> | <string> ]? , <color>? ]! )
<image-set()> = image-set( <image-set-option># )
<element()> = element( <id-selector> )
<cross-fade()> = cross-fade( <cf-mixing-image> , <cf-final-image>? )
<gradient> = <linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()>

where
<length-percentage> = <length> | <percentage>
<shape-radius> = <length-percentage> | closest-side | farthest-side
<position> = [[ left | center | right | top | bottom | <length-percentage> ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ] | [ center | [ left | right ] <length-percentage>? ] && [ center | [ top | bottom ] <length-percentage>? ]]
<fill-rule> = nonzero | evenodd
<color> = <rgb()> | <rgba()> | <hsl()> | <hsla()> | <hex-color> | <named-color> | currentcolor | <deprecated-system-color>
<image-set-option> = [ <image> | <string> ] <resolution>
<cf-mixing-image> = <percentage>? && <image>
<cf-final-image> = <image> | <color>
<linear-gradient()> = linear-gradient( [ <angle> | to <side-or-corner> ]? , <color-stop-list> )
<repeating-linear-gradient()> = repeating-linear-gradient( [ <angle> | to <side-or-corner> ]? , <color-stop-list> )
<radial-gradient()> = radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )
<repeating-radial-gradient()> = repeating-radial-gradient( [ <ending-shape> || <size> ]? [ at <position> ]? , <color-stop-list> )

where
<rgb()> = rgb( [ [ <percentage>{3} | <number>{3} ] [ / <alpha-value> ]? ] | [ [ <percentage>#{3} | <number>#{3} ] , <alpha-value>? ] )
<rgba()> = rgba( [ [ <percentage>{3} | <number>{3} ] [ / <alpha-value> ]? ] | [ [ <percentage>#{3} | <number>#{3} ] , <alpha-value>? ] )
<hsl()> = hsl( [ <hue> <percentage> <percentage> [ / <alpha-value> ]? ] | [ <hue>, <percentage>, <percentage>, <alpha-value>? ] )
<hsla()> = hsla( [ <hue> <percentage> <percentage> [ / <alpha-value> ]? ] | [ <hue>, <percentage>, <percentage>, <alpha-value>? ] )
<side-or-corner> = [ left | right ] || [ top | bottom ]
<color-stop-list> = <color-stop>#{2,}
<ending-shape> = circle | ellipse
<size> = closest-side | farthest-side | closest-corner | farthest-corner | <length> | <length-percentage>{2}

where
<alpha-value> = <number> | <percentage>
<hue> = <number> | <angle>
<color-stop> = <color> <length-percentage>?

Example

CSS content

.main {
  width: 500px;
}
.left,
.right {
  width: 40%;
  height: 12ex;
  background-color: lightgray;
}
.left {
  -webkit-shape-outside: polygon(0 0, 100% 100%, 0 100%);
  shape-outside: polygon(0 0, 100% 100%, 0 100%);
  float: left;
  -webkit-clip-path: polygon(0 0, 100% 100%, 0 100%);
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}
.right {
  -webkit-shape-outside: polygon(100% 0, 100% 100%, 0 100%);
  shape-outside: polygon(100% 0, 100% 100%, 0 100%);
  float: right;
  -webkit-clip-path: polygon(100% 0, 100% 100%, 0 100%);
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}
p {
  text-align: center;
}

HTML content

<div class="main">
  <div class="left"></div>
  <div class="right"></div>
  <p>
    Sometimes a web page's text content appears to be
    funneling your attention towards a spot on the page
    to drive you to follow a particular link.  Sometimes
    you don't notice.
  </p>
</div>

Output

Specifications

Specification Status Comment
CSS Shapes Module Level 1
The definition of 'shape-outside' in that specification.
Candidate Recommendation Initial definition

Browser compatibility

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support 37 No support[1] No support 24 8.0 -webkit
<gradient> ? No support No support ? ?
inset() ? No support[2] No support ? ?
polygon() ? No support[3] No support ? ?
Feature Android Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile
Basic support No support No support[1] No support No support 8.0 -webkit
<gradient> No support No support No support No support ?
inset() No support No support[2] No support No support ?
polygon() No support No support[3] No support ? ?

[1] This feature is implemented behind the preference layout.css.shape-outside.enabled, defaulting to false, since Gecko 53.0 (Firefox 53 / Thunderbird 53 / SeaMonkey 2.50), currently only supporting <shape-box> values (see bug 1309467), circle() (see bug 1311244) and ellipse() (see bug 1326406). See bug 1098939 for the general implementation of shape-outside.

[2] Since Gecko 54.0, inset() values have also been supported in Gecko, albeit behind the layout.css.shape-outside.enabled preference.

[3] Since Gecko 55.0, polygon() values have also been supported in Gecko, albeit behind the layout.css.shape-outside.enabled preference.

See also

Document Tags and Contributors

 Last updated by: chrisdavidmills,