Cut rendering cost on initial load with content-visibility
Rendering a page means styling, laying out, painting, and hit-testing everything in the DOM — whether it is on screen or not. For content-heavy pages, that work can stall initial load and make early interactions sluggish. The CSS content-visibility property lets the browser skip rendering for elements that are off-screen, deferring that work until the element approaches the viewport.
What content-visibility: auto does
The property builds on CSS containment. Containment gives the browser predictable isolation of a DOM subtree, so it can optimize rendering without inspecting descendants. The contain property supports four types: size, layout, style, and paint. Each lets the browser skip a different part of rendering for that subtree. Finding the right combination manually is finicky, and content-visibility applies the winning set for you.
Applying content-visibility: auto to an element gives it layout, style, and paint containment. When that element is off-screen and not otherwise relevant (for example, no focus or selection inside it), the browser also applies size containment and skips painting and hit-testing the contents. The element is laid out as if it were empty, and styling and layout of its subtree are skipped entirely. As the element scrolls into view, the browser drops the size containment and renders the content just in time for the user to see it.
Keep a placeholder size with contain-intrinsic-size
That size containment comes with a catch: an off-screen element with no explicit height lays out as a box of zero height. In a page with many off-screen sections, that collapses the scrollbar and shifts layout as content loads. The companion property contain-intrinsic-size establishes the element's natural size when it is under size containment. Set it to an estimate of the element's rendered size, and the browser lays the element out as if it contained a child of those dimensions.
The auto keyword for contain-intrinsic-size refines this further. With a rule like contain-intrinsic-size: auto 300px, the element starts with the 300px placeholder, but once its contents actually render, the browser remembers the real rendered size and reuses it on subsequent off-screen cycles. Infinite scrollers benefit especially: scroll an item off-screen and back, and the browser keeps the correct dimensions rather than reverting to the placeholder.
Accessibility and hidden content
Important to know: content in an element with content-visibility: auto stays in the accessibility tree while off-screen and unrendered. That means it remains searchable and navigable, and it avoids one of the downsides of lightweight hiding. But it also means elements that use styling tactics like display: none or visibility: hidden also remain in the accessibility tree until they enter the viewport, since those styles are not applied while the content is unrendered. To prevent leftover landmark noise, add aria-hidden="true" alongside those style rules.
Measuring the win: a travel blog example
Consider a travel blog page made of separate story sections, each with images and text. By default, the browser styles and lays out every story — even the ones nowhere near the viewport — as soon as they download. That work is pure overhead on initial load. Applying content-visibility: auto to each story section changes the behavior: the browser fully renders only the visible stories and treats off-screen ones as empty boxes for style and layout purposes. Rendering cost on the page drops substantially, often 50% or more. In a representative test, rendering time for the page went from 232ms to 30ms.
The markup stays simple — wrap each story in its own section element and add one CSS rule:
.story { content-visibility: auto; contain-intrinsic-size: 1000px; }
Using content-visibility: hidden for cached state
The auto value handles off-screen optimization, but it does not keep content unrendered once it enters the viewport. content-visibility: hidden covers that case: it hides the element and keeps its rendering state cached, but never renders it automatically — even when it scrolls on-screen. When you remove the property, the element appears immediately using the preserved state.
Unlike display: none, which tears down rendering state and makes re-display expensive, content-visibility: hidden keeps the subtree warm for fast re-entry. Unlike visibility: hidden, it does not hold geometric space or continue to update rendering state while hidden. It is well suited for advanced virtual scrollers, layout measurement, and single-page applications where inactive views stay mounted in the DOM and can be shown again with little cost.
Interaction to Next Paint (INP) benefits
INP measures how reliably a page responds to user input. Rendering work that occupies the main thread during load or interaction leaves less time for the browser to respond to taps and clicks. Deferring layout and painting of off-screen content with content-visibility frees up the main thread, particularly during startup when rendering demand peaks. For pages that are input-heavy early in their lifecycle, that can translate directly to a better INP score.
What this means for your workflow
Adopting content-visibility is primarily a CSS change, but it comes with real responsibilities. Because the browser skips rendering work for off-screen elements, you need to ensure that any content relying on auto visibility has explicit dimensions to avoid layout shifts when it scrolls into view. Elements with dynamic or unknown heights should either use contain-intrinsic-size to reserve space or avoid content-visibility: auto altogether.
Another practical consideration is that content-visibility affects how the browser calculates layout and hit-testing. While this is generally beneficial, any JavaScript that measures element positions or sizes immediately after a scroll event may need adjustments. The browser may not have rendered off-screen content yet, so you cannot assume all layout information is current until the element is actually near the viewport.
Getting started
The most straightforward approach is to apply content-visibility: auto to large, self-contained sections of your page — such as article bodies, comment threads, or gallery grids. For elements that are visible initially, the property has no perceptible effect, so it is safe to apply broadly. The performance gains appear as the user scrolls, since the browser skips style, layout, and paint work for sections that are far from the viewport.
You will also want to pair this with contain-intrinsic-size. This property tells the browser how much space to reserve for an element before it is actually rendered. Without it, elements with content-visibility: auto may collapse to zero height, causing the page to jump as the user scrolls through long documents.
/* Example: reserving space for long-form content */
.card {
content-visibility: auto;
contain-intrinsic-size: 0 500px;
}
The two values in contain-intrinsic-size represent the width and height to reserve. In this case, the card is given an estimated height of 500px before actual rendering occurs.
Browser support and fallbacks
As of this writing, content-visibility is supported in Chromium-based browsers (Chrome 85+, Edge 85+), and support is rolling out to other engines. For browsers that do not support the property, the CSS rule is simply ignored, and the page renders as it normally would. That makes it a safe progressive enhancement — there is no functional breakage, only a missed performance opportunity.
To layer in a safe fallback, you can provide a default size or structure first, then override it where content-visibility is available. For example, you could set a fixed min-height on sections in the base CSS and then apply contain-intrinsic-size inside an @supports block that also enables content-visibility.
Where the real gains come from
The largest improvements come from pages with large, repetitive UI blocks: long feeds, dashboards with many widgets, or archive pages with dozens of entries. In these scenarios, initial load time and scroll responsiveness improve because the browser does not need to process the full document at once.
But content-visibility is not a substitute for other performance practices like lazy-loading images or code-splitting. It targets the rendering pipeline — style recomputation, layout, and paint — rather than network or memory usage. For a comprehensive approach, treat content-visibility as one tool among many: use it for the big, static sections of your UI, and keep the smaller optimizations for images, fonts, and script execution where they belong.



