What Is CSS Containment?
CSS containment improves the performance of web pages by allowing the browser to isolate a subtree of the page from the rest of the page. When the browser understands that a part of the page is independent from the rest, rendering can be optimized and performance improved significantly.
Web pages often contain multiple sections which are logically independent of each other--blogs contain articles, dashboards contain widgets, and feeds contain cards. While developers know these sections are self-contained, browsers traditionally treat the entire document as an interconnected system.
Without containment, the browser must recalculate layout and repaint whenever any element changes, because it cannot know whether the change might affect other parts of the page. Consider a blog with dozens of articles: when a new article is appended, the browser might need to recalculate the entire page layout because it does not know that each article is self-contained. This conservative approach ensures correctness but sacrifices performance, leading to slower page loads, janky scrolling, and reduced responsiveness.
In modern web development with frameworks like Next.js, performance is not just a nicety but a requirement. Core Web Vitals metrics like Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS) directly impact search rankings and user experience. CSS containment provides a declarative, standards-based approach to optimizing rendering performance without requiring JavaScript-based solutions or complex component architectures.
Performance Impact
4
Types of Containment
3
Content-Visibility Values
52
Chrome Version Support
Chrome, Firefox, Safari
Browser Support
The contain Property
The contain property is the primary tool for applying CSS containment. It accepts several values that control what aspects of rendering are contained.
Containment Types
There are four types of containment that can be applied independently or combined: layout, paint, size, and style. Each type addresses a specific aspect of the rendering pipeline, allowing developers to fine-tune performance optimizations based on their use case. For teams building modern web applications, understanding these containment types is essential for creating performant user experiences.
Layout containment (contain: layout) tells the browser that the internal layout of the element is separate from the rest of the page. This means that when the element's contents change size or position, the browser only needs to recalculate layout within that element rather than considering the entire document.
When layout containment is applied:
- Float layout is performed independently
- Margins do not collapse across the containment boundary
- The container becomes a containing block for absolutely and fixed positioned descendants
- The containing box establishes a stacking context
.card {
contain: layout;
}
Special Values
Two special shorthand values combine multiple containment types:
content: This value turns on layout, paint, and style containment. It is a safe value to apply widely because it omits size containment, preventing the common issue of zero-sized elements.
/* Equivalent to: contain: layout paint style */
.article {
contain: content;
}
strict: This declaration behaves the same as contain: size layout paint style, providing the most containment possible. However, it is riskier because it applies size containment. Always set a size when using strict:
.panel {
contain: strict;
contain-intrinsic-size: 400px auto;
}
The content-visibility Property
The content-visibility property takes containment a step further by controlling whether an element renders its contents at all. This enables user agents to skip rendering work entirely until the content becomes relevant.
Values
visible: The default behavior--element contents are laid out and rendered as normal.
hidden: The element skips its contents completely. The skipped contents are not accessible to user agent features like find-in-page, tab-order navigation, or selection.
auto: This is where the real performance magic happens. When set to auto, the element turns on layout containment, style containment, and paint containment as if contain: content was set. If the element is not relevant to the user, its contents are skipped. Unlike hidden, the skipped content remains focusable, selectable, in regular tab order, and available to in-content search.
An element becomes "relevant to the user" when it appears in the viewport or within a user-agent-defined margin around the viewport, when it or its contents receive focus, when it or its contents are selected, or when it or its contents are placed in the top layer.
/* Skip rendering for offscreen content */
.article {
content-visibility: auto;
}
This pattern is particularly effective for long pages with many sections, such as blog archives, infinite scroll feeds, or documentation sites. When combined with CSS transforms, you can create smooth, performant animations while minimizing browser reflow.
Practical Implementation Patterns
Blog and Article Layouts
For blog templates, applying contain: content to each article element is a straightforward optimization that provides significant benefits:
article {
contain: content;
margin-bottom: 2rem;
}
This ensures that when articles are added, removed, or modified, the browser does not need to recalculate layout for the entire page.
Dashboard Widgets
Dashboard components benefit from explicit containment because widgets are typically independent:
.widget {
contain: layout paint;
border: 1px solid #e0e0e0;
border-radius: 8px;
}
Infinite Scroll and Lazy Loading
For infinite scroll implementations, content-visibility: auto provides a CSS-first approach to skipping off-screen content rendering:
.feed-item {
content-visibility: auto;
contain-intrinsic-size: 0 300px; /* Prevent CLS */
}
The contain-intrinsic-size is important here to prevent layout shift when content loads. This technique works well alongside CSS nesting to create maintainable, performant component styles.
Integration with Next.js
In Next.js applications, CSS containment can be applied at multiple levels for optimal web performance:
Global Styles
Apply to commonly-contained elements in your global CSS:
/* globals.css */
article,
section,
.card {
contain: content;
}
CSS Modules and Styled Components
For component-scoped styles:
/* Article.module.css */
.article {
contain: content;
contain-intrinsic-size: auto 400px;
}
@media (prefers-reduced-motion: no-preference) {
.article {
content-visibility: auto;
}
}
Tailwind CSS
Using Tailwind's arbitrary values or custom utilities:
/* In your CSS layer */
@layer utilities {
.contain-content {
contain: content;
}
.content-visibility-auto {
content-visibility: auto;
}
}
Then apply in components with className:
function Article({ children }) {
return (
<article className="contain-content content-visibility-auto">
{children}
</article>
);
}
Best Practices and Guidelines
When to Use Containment
Apply containment to elements that are:
- Logically independent from surrounding content
- Frequently updated or modified
- Part of repetitive patterns (lists, grids, feeds)
- Likely to be off-screen initially
When Not to Use Containment
Avoid containment when elements:
- Have content that overflows intentionally
- Depend on parent's size calculations
- Need cross-boundary style interactions
- Are frequently resized dynamically
Size Containment Considerations
Size containment requires explicit sizing to avoid zero-sized elements. Use contain-intrinsic-size to provide a placeholder:
.collapsible {
contain: size;
contain-intrinsic-size: 0 200px;
}
.collapsible.expanded {
contain-intrinsic-size: auto 500px;
}
Progressive Enhancement
Combine containment with feature queries for graceful degradation:
@supports (contain: content) {
.article {
contain: content;
}
}
@supports (content-visibility: auto) {
.article {
content-visibility: auto;
}
}
Browser Compatibility
CSS containment is well-supported across modern browsers:
- Chrome/Edge: Full support since version 52
- Firefox: Full support since version 53
- Safari: Full support since version 15.4
- Opera: Full support since version 39
For content-visibility: auto, browser support is similarly broad, making it safe to use in production.
Frequently Asked Questions
Does CSS containment work with all browsers?
CSS containment has excellent browser support. Chrome/Edge support it since version 52, Firefox since version 53, and Safari since version 15.4. The `content-visibility` property has similarly broad support.
Can I use containment with flexbox or grid layouts?
Yes, containment works with flexbox and grid layouts. Applying `contain: layout` or `contain: content` to grid or flex items is perfectly valid and can improve performance.
Will containment break my accessibility features?
No, accessibility is preserved. With `content-visibility: auto`, content remains in the accessibility tree, focusable, and searchable. Only `content-visibility: hidden` removes content from accessibility features.
How do I measure the performance impact of containment?
Use Chrome DevTools Performance panel to compare layout and paint operations before and after applying containment. Monitor Core Web Vitals, particularly CLS and INP, to ensure positive impact.
Should I apply containment to every element?
No, containment is not a universal solution. Apply it selectively to elements that are truly independent and benefit from isolation. Over-applying containment adds complexity without benefit.
What happens if I use size containment without specifying contain-intrinsic-size?
The element may be rendered with zero size because the browser treats it as having no children. Always specify `contain-intrinsic-size` when using size containment.
Conclusion
CSS containment provides a declarative, standards-based approach to optimizing rendering performance. By using contain and content-visibility, developers can communicate element independence to the browser, enabling it to skip unnecessary calculations and deliver faster, smoother experiences.
Key takeaways:
- Use
contain: contentas a safe default for independent components - Apply
content-visibility: autoto skip rendering off-screen content - Pair containment with
contain-intrinsic-sizewhen using size containment - Test performance impact using DevTools before and after implementation
- Combine with feature queries for progressive enhancement
Start by applying containment to repetitive components in your application, measure the performance improvement, and expand to other areas as appropriate. For teams building modern web applications, CSS containment is an essential tool in the performance optimization toolkit.
Need help optimizing your Next.js application's performance? Our team specializes in building high-performance web applications using modern CSS techniques. Contact us to discuss your project.
CSS Nesting
Learn how to nest CSS rules naturally, reducing boilerplate and improving maintainability.
Learn moreCSS Transforms
Master 2D and 3D CSS transforms for creating engaging visual effects without performance penalties.
Learn moreCSS Easing Functions
Create smooth, natural animations using CSS easing functions for better user experiences.
Learn more