This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2022.
The contain CSS property indicates that an element and its contents are, as much as possible, independent from the rest of the document tree. Containment enables isolating a subsection of the DOM, providing performance benefits by limiting calculations of layout, style, paint, size, or any combination to a DOM subtree rather than the entire page. Containment can also be used to scope CSS counters and quotes.
contain: none;
contain: size;
contain: layout;
contain: paint;
contain: strict;
<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.
Note: Using layout, paint, strict or content values for this property creates:
position property is absolute or fixed)./* 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;
The contain property can have any of the following values:
none or
size (or inline-size), layout, style, and paint in any order or
strict or content
The keywords have the following meanings:
noneThe element renders as normal, with no containment applied.
strictAll containment rules are applied to the element. This is equivalent to contain: size layout paint style.
contentAll containment rules except size are applied to the element. This is equivalent to contain: layout paint style.
sizeSize 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-sizeInline 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.
layoutThe 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.
styleFor 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.
paintDescendants 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.
| Initial value | none |
|---|---|
| Applies to | all elements |
| Inherited | no |
| Computed value | as specified |
| Animation type | Not animatable |
contain =
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>
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>
.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:
| Specification |
|---|
| CSS Containment Module Level 2> # contain-property> |
| Desktop | Mobile | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | WebView Android | WebView on iOS | |
contain |
52 | 79 | 69 | 39 | 15.4 | 52 | 79 | 41 | 15.4 | 6.0 | 52 | 15.4 |
content |
52 | 79 | 69 | 39 | 15.4 | 52 | 79 | 41 | 15.4 | 6.0 | 52 | 15.4 |
inline-size |
105 | 105 | 101 | 91 | 16 | 105 | 101 | 72 | 16 | 20.0 | 105 | 16 |
layout |
52 | 79 | 69 | 39 | 15.4 | 52 | 79 | 41 | 15.4 | 6.0 | 52 | 15.4 |
none |
52 | 79 | 69 | 39 | 15.4 | 52 | 79 | 41 | 15.4 | 6.0 | 52 | 15.4 |
paint |
52 | 79 | 69 | 39 | 15.4 | 52 | 79 | 41 | 15.4 | 6.0 | 52 | 15.4 |
size |
52 | 79 | 69 | 39 | 15.4 | 52 | 79 | 41 | 15.4 | 6.0 | 52 | 15.4 |
strict |
52 | 79 | 69 | 39 | 15.4 | 52 | 79 | 41 | 15.4 | 6.0 | 52 | 15.4 |
style |
52Before Chrome 115, style containment did not affect quotes, see bug 40592922. |
79Before Edge 115, style containment did not affect quotes, see bug 40592922. |
103 | 39Before Opera 101, style containment did not affect quotes, see bug 40592922. |
15.4Style containment does not affect quotes, see bug 232083. |
52Before Chrome Android 115, style containment did not affect quotes, see bug 40592922. |
103 | 41Before Opera Android 77, style containment did not affect quotes, see bug 40592922. |
15.4Style containment does not affect quotes, see bug 232083. |
6.0Before Samsung Internet 23.0, style containment did not affect quotes, see bug 40592922. |
52Before WebView Android 115, style containment did not affect quotes, see bug 40592922. |
15.4Style containment does not affect quotes, see bug 232083. |
content-visibility propertyposition property
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/CSS/contain