CSS properties - contain

revision:


CSS "contain" 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.

- 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.

Syntax : contain = none | strict | content | [ [ size | inline-size ] || layout || style || paint ]

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;
        

Setting "contain" via JavaScript

1 - inline style assignment

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';
                });
            

2 - CSSOM (dynamic stylesheet injection

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);
            

3 - conditional containment (viewport/state)

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();
            
            

4 - toggle containment on interaction

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';
                });
            

5 - lazy load + containment

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'));
            

6 - smart containment for off-screen elements

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);
                });
            

types of CSS containment

paint containment

- 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.

position: fixed
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>
        

layout containment

- 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.

float: left
position: fixed
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>
        

size containment

- 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.

Size Containment Example

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.

float: left
position: fixed
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>
        

style containement

- 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.

No containment
No containment
No containment
No containment
No containment
No containment
No containment
No containment
No containment
No containment
No containment
No 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>
        

Practical use cases for CSS containment

optimizing layout performance

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.

amet sit sit adipiscing ipsum lorem amet amet consectetur amet sit lorem adipiscing elit amet amet elit consectetur
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
adipiscing consectetur adipiscing elit lorem consectetur adipiscing lorem lorem ipsum elit amet dolor dolor consectetur adipiscing ipsum sit elit sit lorem elit amet dolor
elit sit lorem sit sit dolor lorem ipsum adipiscing ipsum amet amet consectetur adipiscing amet consectetur adipiscing dolor ipsum consectetur sit adipiscing
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
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>
        

improving animations

Animated Content working independently w/o affecting other page contents

With CSS Containment (Strict)

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>
        

fixing layout shifts

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.

A sample CTA button...

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>