revision:
- 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.
- 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.
Property values:
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".
Containment rules :
"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" 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" containment : 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" containment : 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" containment : 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.
Syntax examples
/* 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;
code:
// Single element
const widget = document.querySelector('.widget');
widget.style.contain = 'content'; // or 'strict', 'layout paint', etc.
// Multiple elements
document.querySelectorAll('.list-item').forEach(item => {
item.style.contain = 'content';
});
code:
// Create and inject a style rule
const style = document.createElement('style');
style.textContent = `
.contained-component {
contain: content;
contain-intrinsic-size: 300px 200px;
}
`;
document.head.appendChild(style);
// Or modify existing stylesheet
const sheet = document.styleSheets[0];
sheet.insertRule('.dynamic-element { contain: strict; }', sheet.cssRules.length);
code:
const heavyWidget = document.getElementById('data-viz');
function updateContainment() {
if (heavyWidget.offsetWidth > 500) {
heavyWidget.style.contain = 'strict';
heavyWidget.style.containIntrinsicSize = '600px 400px';
} else {
heavyWidget.style.contain = 'content';
}
}
// React to resize
window.addEventListener('resize', updateContainment);
updateContainment();
code:
const collapsible = document.querySelector('.collapsible-panel');
const toggleBtn = document.querySelector('.toggle-btn');
toggleBtn.addEventListener('click', () => {
const isExpanded = collapsible.classList.toggle('expanded');
// Remove containment when expanded (needs layout flow)
// Add it back when collapsed (isolated)
collapsible.style.contain = isExpanded ? 'none' : 'content';
});
code:
async function loadWidget(container) {
// Reserve space immediately
container.style.contain = 'size layout paint';
container.style.containIntrinsicSize = '400px 300px';
container.style.opacity = '0.3'; // loading state
try {
const widget = await import('./heavy-widget.js');
container.innerHTML = widget.render();
// Remove size containment after load (keep layout/paint)
container.style.contain = 'content';
container.style.opacity = '1';
} catch (err) {
console.error('Widget load failed', err);
container.style.contain = 'none';
}
}
// Usage
loadWidget(document.getElementById('widget-container'));
code:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const el = entry.target;
if (entry.isIntersecting) {
// Visible: keep paint containment
el.style.contain = 'layout paint';
} else {
// Off-screen: add style containment for full isolation
el.style.contain = 'content';
}
});
}, { threshold: 0.1 });
// Observe all cards
document.querySelectorAll('.card').forEach(card => {
observer.observe(card);
});
- establishes a clear boundary around an element, ensuring its content is only rendered within its visible area.
This optimization technique significantly improves rendering performance by instructing the browser only to paint the visible portions of the element, omitting any content that falls outside its bounds.
This element can be switched from no containment to 'paint,' and it shows only the things that are within its bounds.
code:
<div class="site-wrapper">
<div class="switch-holder">
<input type="checkbox" id="containment-switch" />
<label for="containment-switch">Toggle "paint" containment</label>
</div>
<div class="target-element">
<p>This element can be switched from no containment to 'paint,' and it
shows only the things that are within its bounds.</p>
<div class="target-child target-child--fixed">position: fixed</div>
</div>
</div>
<style>
input, button, select { font: inherit; }
label { cursor: pointer; user-select: none;}
p + p, .wrapper-row + .wrapper-row { margin-top: 1.5em;}
.site-wrapper {margin: 0 auto; padding: 2em; max-width: 36em; max-height: 20em; background-color: #fff; }
:root { font-size: 120%;
--containment-hue: 150;
--no-containment-hue: 25;
--containment-text-color: hsl(var(--containment-hue) 50% 40%);
--containment-bg-color: hsl(var(--containment-hue) 80% 95%);
--no-containment-text-color: hsl(var(--no-containment-hue) 95% 50%);
--no-containment-bg-color: hsl(var(--no-containment-hue) 95% 95%); }
.site-wrapper { max-width: 30em;}
.target-element { padding: 2em; color: var(--no-containment-text-color); background-color: var(--no-containment-bg-color);}
.target-element, .target-child { padding: 1em; border: 2px dashed; border-radius: 0.5em; }
.target-element--with-containment { contain: paint; color: var(--containment-text-color); background-color: var(--containment-bg-color); }
.target-child--floated { float: left; }
.target-child--fixed { position: fixed; right: 1em; }
.target-child { margin-top: 1em; line-height: 1; }
.switch-holder { text-align: center; }
.switch-holder + .target-element { margin-top: 1em;}
</style>
This text will be clipped to the bounds of the box.
This text will not be clipped to the bounds of the box.
code:
<div class="none">
<div class="contain-paint one">
<p>This text will be clipped to the bounds of the box.</p>
</div>
<div class=" one">
<p>This text will not be clipped to the bounds of the box.</p>
</div>
</div>
<style>
.one{ width: 100px; height: 100px; background: red; margin: 10px; font-size: 30px;}
.contain-paint { contain: paint;}
</style>
- establishes a protective border around an element, keeping its internal layout separate from external influences and vice versa. This turns the component into a containing block, forming its independent stacking context.
The stacking context organizes elements in a hierarchy, deciding their position relative to others.
This element can be switched from no containment to `layout`, automatically clearing a child's float and including the fixed-positioned child.
code:
<div class="site-wrapper1">
<div class="switch-holder1">
<input type="checkbox" id="containment-switch1" />
<label for="containment-switch1">Toggle "layout" containment</label>
</div>
<div class="target-element1">
<p>
This element can be switched from no containment to `layout`,
automatically clearing a child's float and including the
fixed-positioned child.
</p>
<div class="target-child1 target-child--floated1">float: left</div>
<div class="target-child1 target-child--fixed1">position: fixed</div>
</div>
</div>
<style>
input, button, select { font: inherit; }
label { cursor: pointer; user-select: none;}
p + p, .wrapper-row1 + .wrapper-row1 { margin-top: 1.5em;}
.site-wrapper1 {margin: 0 auto; padding: 2em; max-width: 36em; max-height: 20em; background-color: #fff; }
:root { font-size: 120%; --containment-hue: 150; --no-containment-hue: 25; --containment-text-color: hsl(var(--containment-hue) 50% 40%);
--containment-bg-color: hsl(var(--containment-hue) 80% 95%); --no-containment-text-color: hsl(var(--no-containment-hue) 95% 50%);
--no-containment-bg-color: hsl(var(--no-containment-hue) 95% 95%); }
.site-wrapper1 { max-width: 30em;}
.target-element1 { padding: 2em; color: var(--no-containment-text-color); background-color: var(--no-containment-bg-color);}
.target-element1, .target-child1 { padding: 1em; border: 2px dashed; border-radius: 0.5em; }
.target-element--with-containment1 { contain: paint; color: var(--containment-text-color); background-color: var(--containment-bg-color); }
.target-child--floated1 { float: left; }
.target-child--fixed1 { position: fixed; right: 1em; }
.target-child1 { margin-top: 1em; line-height: 1; }
.switch-holder1 { text-align: center; }
.switch-holder1 + .target-element1 { margin-top: 1em;}
</style>
<script>
const containmentSwitch1 = document.querySelector("#containment-switch1");
const targetElement1 = document.querySelector(".target-element1");
if (containmentSwitch && targetElement) {
containmentSwitch1.addEventListener("change", (e) => {
if (!e.target.checked) {
targetElement1.classList.remove("target-element--with-containment");
} else {
targetElement1.classList.add("target-element--with-containment");
}
});
}
</script>
- instructs the browser to treat an element as if it has no content when determining its size. This means that the browser disregards the intrinsic dimensions of the element’s contents and instead relies solely on the specified size properties, such as width and height. This optimization technique is beneficial in situations where the size of an element is dynamically modified using JavaScript or other code, as it prevents an infinite loop of size calculations.
This is an example of size containment using HTML and CSS.
code:
<div class="container spec-1">
<div class="inner">
<div class="demo-content">
<h3>Size Containment Example</h3>
<p>This is an example of size containment using HTML and CSS.</p>
</div>
</div>
</div>
<style>
.container { width: 500px; height: 300px; border: 1px solid black; padding: 20px; box-sizing: border-box; }
.inner {width: 100%; height: 100%; background-color: lightblue; display: flex; justify-content: center; align-items: center; }
.demo-content { width: 80%; height: 80%; background-color: white; border: 1px solid black; display: flex; justify-content: center; align-items: center; }
</style>
When switched from no containment to 'size,' this division doesn't change its dimensions based on its contents.
code:
<div class="site-wrapper2">
<div class="switch-holder2">
<input type="checkbox" id="containment-switch2" />
<label for="containment-switch2">Toggle "size" containment</label>
</div>
<div class="target-element2">
<p>When switched from no containment to 'size,' this division doesn't
change its dimensions based on its contents. </p>
<div class="target-child2 target-child--floated2">float: left</div>
<div class="target-child2 target-child--fixed2">position: fixed</div>
</div>
</div>
<style>
input, button, select { font: inherit; }
label { cursor: pointer; user-select: none;}
p + p, .wrapper-row2 + .wrapper-row2 { margin-top: 1.5em;}
.site-wrapper2 {margin: 0 auto; padding: 2em; max-width: 36em; max-height: 20em; background-color: #fff; }
:root { font-size: 120%;
--containment-hue: 150;
--no-containment-hue: 25;
--containment-text-color: hsl(var(--containment-hue) 50% 40%);
--containment-bg-color: hsl(var(--containment-hue) 80% 95%);
--no-containment-text-color: hsl(var(--no-containment-hue) 95% 50%);
--no-containment-bg-color: hsl(var(--no-containment-hue) 95% 95%); }
.site-wrapper2 { max-width: 30em;}
.target-element2 { padding: 2em; color: var(--no-containment-text-color);
background-color: var(--no-containment-bg-color);}
.target-element2, .target-child2 { padding: 1em; border: 2px dashed; border-radius: 0.5em; }
.target-element--with-containment2 { contain: paint; color: var(--containment-text-color);
background-color: var(--containment-bg-color); }
.target-child--floated2 { float: left; }
.target-child--fixed2 { position: fixed; right: 1em; }
.target-child2 { margin-top: 1em; line-height: 1; }
.switch-holder2 { text-align: center; }
.switch-holder2 + .target-element2 { margin-top: 1em;}
</style>
<script>
const containmentSwitch2 = document.querySelector("#containment-switch2");
const targetElement2 = document.querySelector(".target-element2");
const randomText = [
"When switched from no containment to 'size,' this division doesn't change its dimensions based on its contents.",
"This type of containment is helpful when an element has dynamic elements that change repeatedly and
you don't want the browser to work continuously for the element's dimensions based on its contents."
];
let currentIndex = 0;
let msgInterval = 3000;
if (containmentSwitch2 && targetElement2) {
setInterval(() => {
targetElement2.querySelector("p").textContent = randomText[currentIndex];
currentIndex = (currentIndex + 1) % randomText.length;
}, msgInterval);
containmentSwitch2.addEventListener("change", (e) => {
if (!e.target.checked) {
targetElement2.classList.remove("target-element--with-containment");
} else {
targetElement2.classList.add("target-element--with-containment");
}
});
}
</script>
- is a specialized feature designed for counters and quotes. It influences counters and quotes by confining them to the subtree, generating new instances instead of incrementing existing ones. This containment has a narrow scope of implementation benefits and is particularly effective in straightforward scenarios where the style features like counter or quote usage are simple and uncomplicated.
Demonstrating no containment with style containment.
code:
<div class="site-wrapper3">
<p class="intro">Demonstrating no containment with style containment.</p>
<div class="target-element-group3">
<div class="target-element3">
<div class="target-child3">No containment</div>
<div class="target-child3">No containment</div>
<div class="target-child3">No containment</div>
<div class="target-child3">No containment</div>
<div class="target-child3">No containment</div>
<div class="target-child3">No containment</div>
</div>
<div class="target-element3 target-element3">
<div class="target-child3">No containment</div>
<div class="target-child3 target-child--with-containment3">
No containment
</div>
<div class="target-child3">No containment</div>
<div class="target-child3 target-child--with-containment3">
No containment
</div>
<div class="target-child3 target-child--with-containment3">
No containment
</div>
<div class="target-child3">No containment</div>
</div>
</div>
</div>
<style>
input, button, select { font: inherit; }
label { cursor: pointer; user-select: none;}
p + p, .wrapper-row3 + .wrapper-row3 { margin-top: 1.5em;}
.site-wrapper3 {margin: 0 auto; padding: 2em; max-width: 36em; max-height: 70em; background-color: #fff; }
:root { font-size: 120%;
--containment-hue: 150;
--no-containment-hue: 25;
--containment-text-color: hsl(var(--containment-hue) 50% 40%);
--containment-bg-color: hsl(var(--containment-hue) 80% 95%);
--no-containment-text-color: hsl(var(--no-containment-hue) 95% 50%);
--no-containment-bg-color: hsl(var(--no-containment-hue) 95% 95%); }
.site-wrapper3{ max-width: 40em; min-height: 100vh;}
.intro {max-width: 40em;text-align: center;}
.target-element-group3{display: grid; grid-template-columns: repeat(2, 1fr); gap: 2em;}
.target-element3 {padding: 2em; color: var(--no-containment-text-color);
background-color: var(--no-containment-bg-color); counter-reset: list-items; }
.target-child3::before { counter-increment: list-items; content: counter(list-items) ". ";}
.target-element3, .target-child3 {padding: 1em; border: 2px dashed; border-radius: 0.5em;}
.target-child--with-containment3 { contain: style; color: var(--containment-text-color);
background-color: var(--containment-bg-color);}
.target-child3 {margin-top: 1em; line-height: 1;}
.intro + .target-element-group3 { margin-top: 1em;}
</style>
<script>
const containmentSwitch3 = document.querySelector("#containment-switch3");
const targetChildsWithContainment3 = document.querySelectorAll(".target-child--with-containment");
if (targetChildsWithContainment3.length) {
for (const targetChildWithContainment3 of targetChildsWithContainment) {
targetChildWithContainment3.textContent = "Style containment";
}
}
</script>
Set containment via the select box, then use the "Add an item" button to dynamically inject items. Note that CSS containment changes here are not visually apparent but are observable during performance analysis.
code:
<div class="site-wrapper4">
<div class="grid-wrapper4">
<p class="intro4">
Set containment via the select box, then use the "Add an item" button
to dynamically inject items. Note that CSS containment changes here
are not visually apparent but are observable during performance
analysis.
</p>
<div class="controls-wrapper4">
<button id="trigger4">Add an item</button>
<div class="switch-wrapper4">
<label for="containment-switch4">contain: </label>
<select id="containment-switch4">
<option class="containment-none4" value="none">none</option>
<option class="containment-content4" value="content">
content
</option>
</select>
</div>
</div>
<div class="grid4">
<div class="grid-item4">
amet sit sit adipiscing ipsum lorem amet amet consectetur amet sit
lorem adipiscing elit amet amet elit consectetur
</div>
<div class="grid-item4">
consectetur sit consectetur adipiscing sit adipiscing consectetur
dolor amet lorem elit dolor elit lorem lorem amet consectetur
consectetur dolor lorem ipsum dolor lorem adipiscing sit sit
consectetur dolor elit dolor elit elit lorem
</div>
<div class="grid-item4">
adipiscing consectetur adipiscing elit lorem consectetur adipiscing
lorem lorem ipsum elit amet dolor dolor consectetur adipiscing ipsum
sit elit sit lorem elit amet dolor
</div>
<div class="grid-item4">
elit sit lorem sit sit dolor lorem ipsum adipiscing ipsum amet amet
consectetur adipiscing amet consectetur adipiscing dolor ipsum
consectetur sit adipiscing
</div>
<div class="grid-item4">
consectetur elit elit ipsum sit adipiscing adipiscing amet ipsum
dolor lorem elit lorem sit sit amet lorem elit ipsum adipiscing sit
ipsum adipiscing consectetur ipsum consectetur consectetur sit elit
adipiscing sit adipiscing elit adipiscing consectetur amet dolor
dolor dolor lorem sit dolor consectetur consectetur dolor
</div>
</div>
</div>
</div>
<style>
:root {font-size: 120%; --contain: none;}
input, button, select { font: inherit; }
label {cursor: pointer; user-select: none; }
p + p, .wrapper-row4 + .wrapper-row4 { margin-top: 1.5em;}
.site-wrapper4 {margin: 0 auto; padding: 2em; max-width: 50em; background-color: #fff;}
.intro4 { max-width: 40em; color: darkblue; }
.grid-wrapper4 { contain: var(--contain); }
.grid4 {columns: 3; column-gap: 1em; }
.grid-item4 { display: inline-block; padding: 1em; border: 1px dashed; margin-bottom: 1em; border-radius: 0.5em;}
.grid-item4--hl { font-style: italic; }
.grid-item4--hl-none {color: orangered; border-color: orangered;}
.grid-item4--hl-content {color: green; border-color: green; }
.switch-wrapper4 {display: inline-flex; gap: 0.5em; }
.switch-wrapper4 + .grid4-wrapper {margin-top: 2em;}
.controls-wrapper4 { align-items: center; display: flex; justify-content: space-between; margin: 2em 0;}
.containment-none4 { color: orangered;}
.containment-content4 {color: green;}
</style>
<script>
const grid4 = document.querySelector(".grid4");
const gridWrapper4 = document.querySelector(".grid-wrapper4");
const newElementTrigger4 = document.querySelector("#trigger4");
const containmentSwitch4 = document.querySelector("#containment-switch4");
let gridItemHighlighted = "grid-item4--hl-none";
containmentSwitch4.addEventListener("change", (e) => {
gridWrapper4.style.setProperty("--contain", e.target.value);
gridItemHighlighted = `grid-item4--hl-${e.target.value}`;
console.log(e.target.value);
});
function generateRandomSentence() {
const words = [
"lorem",
"ipsum",
"dolor",
"sit",
"amet",
"consectetur",
"adipiscing",
"elit"
];
// Generate a random number of words (between 5 and 15 for example)
const numberOfWords = Math.floor(Math.random() * 36) + 15;
// Select random words from the array
const randomWords = [];
for (let i = 0; i < numberOfWords; i++) {
const randomIndex = Math.floor(Math.random() * words.length);
randomWords.push(words[randomIndex]);
}
// Join the words into a sentence
const sentence = randomWords.join(" ");
return sentence;
}
if (grid4 && newElementTrigger4) {
newElementTrigger4.addEventListener("click", () => {
window.setTimeout(() => {
// Create a new grid item
const newGridItem = document.createElement("div");
newGridItem.className = `grid-item4 grid-item4--hl ${gridItemHighlighted}`;
newGridItem.textContent = generateRandomSentence(); // You can customize the content as needed
// Append the new grid item to the grid
grid4.insertBefore(newGridItem, grid4.firstChild);
}, 1000);
});
}
</script>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorum architecto alias atque minima esse, aliquam nostrum error id veniam! Obcaecati error accusantium quo veniam voluptatum laudantium facilis natus impedit itaque.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque, est dolorum voluptatum eveniet tempora aperiam, nam voluptas molestiae nostrum laboriosam officiis asperiores voluptatibus officia nihil, repellendus voluptates sunt? Inventore, nostrum!
Nihil quae atque, esse doloribus doloremque optio numquam at nisi non eius voluptatum debitis! Ea et enim cumque, voluptatem natus quae vitae ab reiciendis a voluptas nisi pariatur cum perspiciatis.
Voluptas labore omnis nobis earum quis, veritatis saepe fugit ad debitis explicabo inventore similique eaque, nulla minus animi? Neque rerum voluptatibus odio impedit nihil asperiores placeat voluptate velit dolorum perferendis.
code:
<div class="site-wrapper5">
<h4>Animated Content working independently w/o affecting other page contents</h4>
<h5>With CSS Containment (Strict)</h5>
<div class="wrapper-row5">
<div>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolorum
architecto alias atque minima esse, aliquam nostrum error id veniam!
Obcaecati error accusantium quo veniam voluptatum laudantium facilis
natus impedit itaque.
</p>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque,
est dolorum voluptatum eveniet tempora aperiam, nam voluptas
molestiae nostrum laboriosam officiis asperiores voluptatibus
officia nihil, repellendus voluptates sunt? Inventore, nostrum!
</p>
<p>
Nihil quae atque, esse doloribus doloremque optio numquam at nisi
non eius voluptatum debitis! Ea et enim cumque, voluptatem natus
quae vitae ab reiciendis a voluptas nisi pariatur cum perspiciatis.
</p>
<p>
Voluptas labore omnis nobis earum quis, veritatis saepe fugit ad
debitis explicabo inventore similique eaque, nulla minus animi?
Neque rerum voluptatibus odio impedit nihil asperiores placeat
voluptate velit dolorum perferendis.
</p>
</div>
<div class="animated-content-wrapper5">
<div class="animated-content5"></div>
</div>
</div>
</div>
<style>
label {cursor: pointer; user-select: none;}
p + p,.wrapper-row5 + .wrapper-row5 {margin-top: 1.5em;}
.site-wrapper5 { margin: 0 auto; padding: 2em; max-width: 36em;}
.site-wrapper5 { background-color: #fff;}
.animated-content-wrapper5 {contain: strict; }
.animated-content5 { width: 500px; height: 75px; background-color: yellow; animation: anim-1 2s infinite alternate; }
@keyframes anim-1 {
100% {width: 75px; height: 500px; background-color: red; }
}
.wrapper-row5 {display: grid; grid-template-columns: repeat(2, 1fr); gap: 2em; }
</style>
A quick example to show how layout shifts caused by third-party ads can disrupt the user experience, making it difficult to navigate the site smoothly.
The following is a fake third-party ad that loads 1.5 seconds after the page finishes loading, which is a common occurrence with third-party ads.
The above CTA button doesn't shift down the page because the fake ad placed directly above it is no longer causing layout shifts.
It's important to note that if a user intends to click the CTA button and it suddenly gets pushed down the page, it creates a negative user experience and could potentially lead to a lost lead for the website.
I intentionally changed the font size and dimensions of the injected ad to demonstrate that it will not affect the ad container's size in any way due to the strict containment applied to it.
code:
<div class="site-wrapper6">
<p>A quick example to show how layout shifts caused by third-party ads can
disrupt the user experience, making it difficult to navigate the site
smoothly.</p>
<p>The following is a fake third-party ad that loads 1.5 seconds after the
page finishes loading, which is a common occurrence with third-party
ads.</p>
<div id="advert">Loading...</div>
<a href="#" class="cta">A sample CTA button...</a>
<p>The above CTA button doesn't shift down the page because the fake ad placed directly above it is
no longer causing layout shifts.</p>
<p>It's important to note that if a user intends to click the CTA button and it suddenly gets pushed
down the page, it creates a negative user experience and could potentially lead to a lost lead for the website.</p>
<p>I intentionally changed the font size and dimensions of the injected ad to demonstrate that it will
not affect the ad container's size in any way due to the strict containment applied to it.</p>
</div>
<style>
.site-wrapper6 {margin: 0 auto; padding: 2em; max-width: 36em; background-color: #fff;}
#advert {margin: 2em 0; color: red; height: 250px; contain: paint; }
.cta { padding: 1em 2em; background-color: #07c; display: inline-flex; color: white; margin-bottom: 1em;}
</style>
<script>
const content = document.querySelector("#advert");
if (content) {
setTimeout(() => {
content.innerHTML =
"<div style='background-color: #e6e; color: white; font-size: 250%; height: 350px; display: flex;
align-items: center; justify-content: center;'>Advertisement</div>";
}, 1500);
}
</script>