CSS Content-Visibility Table
| Piece | What it does | Field note |
|---|---|---|
content-visibility: auto | Skip offscreen rendering | Layout/paint skipped until near viewport - the free long-page win |
contain-intrinsic-size | The placeholder size | Without it skipped sections have 0 height - scrollbar jumps |
contain: layout paint | The manual dial | content-visibility:auto = contain layout+style+paint CONDITIONALLY |
contain: strict / content | The shorthands | strict adds size - the element keeps its box no matter what |
Skip-to content in DOM | Findable but unrendered | Ctrl-F and accessibility still reach it - rendering skipped, not content |
hidden=until-found | Search reveals | Pairs with cv - browser un-hides on find-in-page automatically |
Renders when relevant | The auto contract | The browser chooses the proximity - ~viewport margin internally |
Measure before/after | The proof | Long pages: paint and layout costs collapse - profile the before |
content-visibility: auto is the one-line rendering win for long pages: sections far from the viewport skip LAYOUT and PAINT entirely - the DOM stays (findable by Ctrl-F and screen readers), only the rendering is skipped, which collapses the cost of 10,000-row feeds and tab-panel graveyards.
Bottom line: the mandatory companion is contain-intrinsic-size - a skipped section has no rendered layout, so without a placeholder size it collapses to zero height and the scrollbar jumps on every scroll. Set intrinsic size, and the page scrolls stably while offscreen sections stay cheap.
The honest part: 'auto' means the browser chooses the proximity - roughly a viewport margin around the visible area - so you cannot control exactly when a section renders, and interactive content (a canvas or video inside) only comes alive when scrolled near. Measure paint cost before and after: the win is real and provable.
How to use
- Apply to long-page sections: section { content-visibility: auto; contain-intrinsic-size: auto 500px; } - the auto keyword remembers the last real size once rendered.
- Give every skipped section an estimate: contain-intrinsic-size: auto 500px (height) - the scrollbar stays honest and jumps disappear.
- Reveal on search: hidden=until-found on collapsed sections - the browser un-hides automatically when the user finds text inside (pairs with CV).
Frequently asked questions
What exactly does content-visibility: auto skip?
Layout and paint for offscreen content - not the content itself. The element's DOM stays fully present: queries find it, Ctrl-F finds it, screen readers read it, and scripts can measure and manipulate it (which will force rendering as needed). What the browser skips while the section is far from the viewport: style/layout/paint containment work - the expensive parts for complex subtrees. The result on a 10,000-item page: initial render cost approaches the cost of one viewport's worth of items instead of all of them. The skipped state is also self-managing - approach the section and the browser renders it before it becomes visible.
Why is contain-intrinsic-size mandatory, and what does the auto keyword inside it do?
Skipped elements have no rendered layout, so their box would be 0x0 - every skipped section collapses, the total page height collapses, and the scrollbar shrinks and jumps as sections render and unrender during scroll. contain-intrinsic-size supplies the ESTIMATED size the browser uses while skipped. The auto keyword inside it (contain-intrinsic-size: auto 500px) adds the memory: once a section HAS been rendered, the browser remembers its real size and uses that as the estimate - so after a first pass through the page, the scrollbar becomes accurate. The initial estimate matters most: wildly wrong guesses still cause scrollbar jumps on first scroll.
How is content-visibility different from lazy-loading content with JavaScript?
Rendering skip versus content absence, and who pays the complexity. The JS approach (IntersectionObserver + conditional rendering) keeps content out of the DOM until proximity - smaller DOM, but findability is lost (Ctrl-F and screen readers miss unrendered sections) and you own the observer plumbing plus render-timing bugs. content-visibility keeps the DOM complete - search and accessibility still see everything - while the browser owns the render scheduling natively. The tradeoffs: CV's browser-controlled proximity is not tunable, and scripts that read layout of skipped elements force renders. For pure long-page performance, CV is the simpler, more complete tool; JS lazy-loading remains for content that is EXPENSIVE TO CREATE, not just to render.
What is the relationship between content-visibility and the contain property?
content-visibility: auto is contain with a conditional brain: it applies layout, style and paint containment WHILE the element is skipped, and relaxes to relevant containment when near the viewport. The contain property is the manual dial: contain: layout isolates the element's internal layout from the page; contain: paint clips overflow and guarantees descendants cannot paint outside; contain: strict (layout+paint+size+style) additionally fixes the element's SIZE - the element's box no longer depends on its contents at all. Manual containment is the tool for widget roots (a map embed that must never affect page layout); content-visibility is the tool for page sections where you want the performance without hand-managing sizes.