<section class="default-example" id="default-example">
<div class="card" id="example-element">
<h2>Element with '<code>contain</code>'</h2>
<p>
The Goldfish is a species of domestic fish best known for its bright
colors and patterns.
</p>
<div class="fixed"><p>Fixed right 4px</p></div>
</div>
</section>
h2 {
margin-top: 0;
}
#default-example {
text-align: left;
padding: 4px;
font-size: 16px;
}
.card {
text-align: left;
border: 3px dotted;
padding: 20px;
margin: 10px;
width: 85%;
min-height: 150px;
}
.fixed {
position: fixed;
border: 3px dotted;
right: 4px;
padding: 4px;
margin: 4px;
}
There are four types of CSS containment: size, layout, style, and paint, which are set on the container. The property is a space-separated list of a subset of the five standard values or one of the two shorthand values. Changes to the contained properties within the container are not propagated outside of the contained element to the rest of the page. The main benefit of containment is that the browser does not have to re-render the DOM or page layout as often, leading to small performance benefits during the rendering of static pages and greater performance benefits in more dynamic applications.
Using the contain
property is useful on pages with groups of elements that are supposed to be independent, as it can prevent element internals from having side effects outside of its bounding-box.
/* Keyword values */
contain: none;
contain: strict;
contain: content;
contain: size;
contain: inline-size;
contain: layout;
contain: style;
contain: paint;
/* Multiple keywords */
contain: size paint;
contain: size layout paint;
contain: inline-size layout;
/* Global values */
contain: inherit;
contain: initial;
contain: revert;
contain: revert-layer;
contain: unset;
Values
The contain
property can have any of the following values:
none
orsize
(or inline-size
), layout
, style
, and paint
in any order orstrict
or content
The keywords have the following meanings:
none
The element renders as normal, with no containment applied.
strict
All containment rules are applied to the element. This is equivalent to contain: size layout paint style
.
content
All containment rules except size
are applied to the element. This is equivalent to contain: layout paint style
.
size
Size containment is applied to the element in both the inline and block directions. The size of the element can be computed in isolation, ignoring the child elements. This value cannot be combined with inline-size
.
inline-size
Inline size containment is applied to the element. The inline size of the element can be computed in isolation, ignoring the child elements. This value cannot be combined with size
.
layout
The internal layout of the element is isolated from the rest of the page. This means nothing outside the element affects its internal layout, and vice versa.
style
For properties that can affect more than just an element and its descendants, the effects don't escape the containing element. Counters and quotes are scoped to the element and its contents.
paint
Descendants of the element don't display outside its bounds. If the containing box is offscreen, the browser does not need to paint its contained elements â these must also be offscreen as they are contained completely by that box. If a descendant overflows the containing element's bounds, then that descendant will be clipped to the containing element's border-box.
contain =Examples Paint containment
none |
strict |
content |
[ [ size | inline-size ] || layout || style || paint ]
The following example shows how to use contain: paint
to prevent an element's descendants from painting outside of its bounds.
div {
width: 100px;
height: 100px;
background: red;
margin: 10px;
font-size: 20px;
}
.contain-paint {
contain: paint;
}
<div class="contain-paint">
<p>This text will be clipped to the bounds of the box.</p>
</div>
<div>
<p>This text will not be clipped to the bounds of the box.</p>
</div>
Layout containment
Consider the example below which shows how elements behave with and without layout containment applied:
<div class="card contain-layout">
<h2>Card 1</h2>
<div class="fixed"><p>Fixed box 1</p></div>
<div class="float"><p>Float box 1</p></div>
</div>
<div class="card">
<h2>Card 2</h2>
<div class="fixed"><p>Fixed box 2</p></div>
<div class="float"><p>Float box 2</p></div>
</div>
<div class="card">
<h2>Card 3</h2>
<!-- ... -->
</div>
p {
margin: 4px;
padding: 4px;
}
h2 {
margin-bottom: 4px;
padding: 10px;
}
div {
border-radius: 4px;
box-shadow: 0 2px 4px 0 gray;
padding: 6px;
margin: 6px;
}
.card {
width: 70%;
height: 90px;
}
.fixed {
position: fixed;
right: 10px;
top: 10px;
background: coral;
}
.float {
float: left;
margin: 10px;
background: aquamarine;
}
.contain-layout {
contain: layout;
}
The first card has layout containment applied, and its layout is isolated from the rest of the page. We can reuse this card in other places on the page without worrying about layout recalculation of the other elements. If floats overlap the card bounds, elements on the rest of the page are not affected. When the browser recalculates the containing element's subtree, only that element is recalculated. Nothing outside of the contained element needs to be recalculated. Additionally, the fixed box uses the card as a layout container to position itself.
The second and third cards have no containment. The layout context for the fixed box in the second card is the root element so the fixed box is positioned in the top right corner of the page. A float overlaps the second card's bounds causing the third card to have unexpected layout shift that's visible in the positioning of the <h2>
element. When recalculation occurs, it is not limited to a container. This impacts performance and interferes with the rest of the page layout.
Style containment scopes counters and quotes to the contained element. For CSS counters, the counter-increment
and counter-set
properties are scoped to the element as if the element is at the root of the document.
The example below takes a look at how counters work when style containment is applied:
<ul>
<li>Item A</li>
<li>Item B</li>
<li class="container">Item C</li>
<li>Item D</li>
<li>Item E</li>
</ul>
body {
counter-reset: list-items;
}
li::before {
counter-increment: list-items;
content: counter(list-items) ": ";
}
.container {
contain: style;
}
Without containment, the counter would increment from 1 to 5 for each list item. Style containment causes the counter-increment
property to be scoped to the element's subtree and the counter begins again at 1:
CSS quotes are similarly affected in that the content
values relating to quotes are scoped to the element:
<!-- With style containment -->
<span class="open-quote">
outer
<span class="contain-style">
<span class="open-quote">inner</span>
</span>
</span>
<span class="close-quote">close</span>
<br />
<!-- Without containment -->
<span class="open-quote">
outer
<span>
<span class="open-quote">inner</span>
</span>
</span>
<span class="close-quote">close</span>
body {
quotes: "[" "]" "â¹" "âº";
}
.open-quote::before {
content: open-quote;
}
.close-quote::after {
content: close-quote;
}
.contain-style {
contain: style;
}
Because of containment, the first closing quote ignores the inner span and uses the outer span's closing quote instead:
Specifications Browser compatibilityLoadingâ¦
See alsocontent-visibility
propertyposition
propertyRetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4