Category pages with hundreds of tiles, landing pages with a dozen sections, documentation pages running to thousands of lines: on pages like these the browser does work that nobody will ever see. It resolves styles, calculates positions and paints content sitting four screen heights below the fold. The CSS property content-visibility targets exactly this: it lets the browser skip rendering entire subtrees for as long as they are not relevant to the user. In the demo used by the Chrome documentation, rendering time on initial load dropped from 232 milliseconds to 30 milliseconds (web.dev). This article explains the mechanics behind it, the four containment types, the right placeholder height to avoid new layout shifts - and the places where the property has no business being.
Why long pages waste rendering work
A browser builds every page in clearly separated stages: it resolves the applicable style for each element (style), determines the position and size of each box (layout), fills pixels (paint) and composes the layers (composite). The crucial point: by default these stages run across the whole document - including the part a visitor would only reach after five seconds of scrolling. On a page with six equally sized sections, of which one and a half fit into the first screen, that means a multiple of the work that is actually required.
This work lands on the main thread - the same thread that processes input. Wasted rendering work therefore hurts twice: it delays the first meaningful paint and makes the page sluggish in its first seconds. Field data shows clearly how large the gap between capable and constrained hardware is. The HTTP Archive Web Almanac 2025 reports that 62 percent of pages reach a good LCP score on mobile, compared with 74 percent on desktop (HTTP Archive Web Almanac 2025). For the interaction metric INP the distance is even more striking: 77 percent good scores on mobile against 97 percent on desktop (HTTP Archive Web Almanac 2025).
Overall, the same analysis finds that 48 percent of mobile and 56 percent of desktop websites pass all Core Web Vitals (HTTP Archive Web Almanac 2025); on mobile the figure climbed from 36 percent in 2023 through 44 percent in 2024 to today's 48 percent (HTTP Archive Web Almanac 2025). The gap between desktop and phone is not caused by slower connections alone but above all by the far tighter CPU budget of affordable devices. That is precisely where every saved style and layout calculation pays off most - a core theme of optimization for mobile devices.
Rendering is not loading
What content-visibility allows the browser to do
The property has three values. visible is the default state and changes nothing. hidden skips the content regardless of where it sits and keeps the rendering state cached - useful for tab panels or views in single-page applications that will be revisited. auto is the interesting case: the element permanently gains layout, style and paint containment, and additionally skips its contents whenever it is not relevant to the user (MDN Web Docs).
/* Repeating sections below the fold */
.product-row,
.faq-block,
.article-section {
content-visibility: auto;
contain-intrinsic-size: auto 480px;
}
/* Retained but currently invisible view (e.g. tab panel) */
.tab-panel[data-inactive] {
content-visibility: hidden;
}The effect is well documented in the Chrome documentation demo: for a long travel blog, rendering time on the initial load fell from 232 milliseconds to 30 milliseconds (web.dev). As a rule of thumb the same source cites a reduction of 50 percent or more in rendering cost during load for pages with a lot of content below the fold (web.dev). For the special case of content-visibility: hidden, the same documentation reports that Facebook engineers observed navigation improvements of up to 250 milliseconds when returning to previously cached views (web.dev).
| Aspect | visible | auto | hidden |
|---|---|---|---|
| Rendering of content | continuous | only when relevant to the user | skipped |
| Containment | none | layout, style, paint (plus size while skipping) | layout, style, paint, size |
| Find in page (Ctrl+F) | finds content | finds content | does not find content |
| Tab order and focus | normal | normal | excluded |
| Typical use | default | long pages with repeating sections | retained views, tab panels |
When an element counts as relevant is precisely defined. According to the specification this is the case when its paint containment box intersects the viewport, when the element or its content is focused, when it or its content is selected, or when it is placed in the top layer (W3C, CSS Containment Module Level 2). Browsers add a safety margin on top: the viewport is treated as the visible area plus a user-agent-defined margin of roughly 50 percent of the viewport dimensions (MDN Web Docs). Content is therefore prepared before it actually scrolls into view.
An element is relevant to the user when it is on screen, when the element or its contents are focused, when the element or its contents are selected, or when it is placed in the top layer.
The four containment types and what they promise
content-visibility is not an isolated trick but a convenient surface over an older mechanism: the CSS property contain. Containment is a promise from the author to the browser - an assurance that certain interactions between an element and the rest of the document are ruled out. Only that promise allows the browser to skip work without risking a wrong result. The contain property has been available across browsers since March 2022 (MDN Web Docs).
layout
The inside of the element forms an independent formatting context. Nothing outside affects the internal layout and vice versa (MDN Web Docs). On a change inside, the browser only has to recalculate this box.
paint
Descendants do not paint outside the box bounds at any point; overflow is clipped to the border box (MDN Web Docs). If the box sits off screen, the browser can skip painting its entire content.
size
The size of the box can be determined without looking at its children (W3C, CSS Containment Module Level 2). Without a value from contain-intrinsic-size, however, the box collapses to zero.
style
Properties with reach beyond the element - CSS counters and quotes, for example - stay scoped to the subtree (MDN Web Docs). A change inside does not have to be traced into other parts of the document.
Two shorthands exist for practical use: contain: content covers layout, paint and style, while contain: strict adds size containment (MDN Web Docs). content-visibility: auto essentially corresponds to contain: content plus the ability to skip painting and hit testing as soon as the element is not relevant. Worth knowing: layout and paint containment turn the element into the containing block for absolutely and fixed positioned descendants and create their own stacking context (MDN Web Docs). Switching on containment changes more than the rendering order.
Containment is a promise, not a wish
contain-intrinsic-size: placeholders without new layout shifts
As soon as an element skips its contents, it additionally gains size containment - so the browser determines its height without looking at the children. Without a further declaration the result is a box of zero height (MDN Web Docs). The consequences are unpleasant and easy to spot: the page briefly becomes very short during load, the scrollbar jumps while scrolling, and anchor navigation lands in the wrong place. That is exactly why every content-visibility: auto needs a placeholder height.
/* Fixed estimate: uniform sections with a known height */
.product-row {
content-visibility: auto;
contain-intrinsic-size: 420px;
}
/* Remembered size: sections of varying height */
.article-section {
content-visibility: auto;
contain-intrinsic-size: auto 480px;
}The second variant is the better choice in most cases. With the keyword auto in front of the length, the browser remembers the size it last actually rendered and uses that instead of the estimate once the element skips its contents again (MDN Web Docs). The declared length then only acts as a starting value for the first pass. For long lists and endlessly appended pages the estimate improves on its own the further a visitor scrolls. The contain-intrinsic-size property has been available across browsers since September 2023 (MDN Web Docs).
A poor estimate creates the very problem you set out to avoid
Telling apart lazy loading, code splitting and containment
Audits regularly surface the assumption that lazy loading and content-visibility are two words for the same thing. That misunderstanding is expensive, because it aims the wrong measure at a symptom. The three techniques attack three different kinds of cost and do not replace one another.
| Technique | What is saved | Affects | Typical trigger in an audit |
|---|---|---|---|
| Lazy loading (images, iframes) | network requests and bytes | data volume, connection usage | many images below the fold |
| Code splitting | parsing and executing JavaScript | main thread blocking, INP | large bundle, long tasks |
| content-visibility | style, layout and paint work | rendering time, first frame | long page, many sections, high node count |
| contain-intrinsic-size | missing height of skipped boxes | scroll height, layout stability | jumping scrollbar, displaced anchors |
The difference is clearest on a page that already applies lazy loading and code splitting properly and still feels sluggish: bytes are lean, the script is split - but the markup itself is long, and the browser still has to lay out every tile. Conversely content-visibility helps little when the real brake is server response time; measures such as 103 Early Hints to use server thinking time are the more fitting answer then. Which kind of cost dominates is decided by measurement, not by habit - the starting point of every structured performance analysis.
Closely related is the view on raw node count. An overcrowded tree makes every style and layout calculation more expensive regardless of containment; trimming the Document Object Model and applying content-visibility therefore complement each other. Containment lowers the cost of the work that occurs; a smaller page lowers the amount of work itself.
Scrollbar, find in page and anchor jumps
The most important difference between content-visibility: auto and classic hiding lies in discoverability. Skipped content stays in the Document Object Model and in the accessibility tree; it remains focusable, selectable, part of the regular tab order and reachable for find in page (MDN Web Docs). This makes it possible to save rendering work without restricting accessibility - a decisive difference from display: none or visibility: hidden.
- Find in page with Ctrl+F locates matches inside skipped sections and scrolls to them
- Tab navigation reaches links and form fields inside skipped areas
- Text selection across several sections keeps working unchanged
- Screen readers announce the content because it stays in the accessibility tree
- Focus or selection make an element relevant immediately and trigger rendering
content-visibility: hidden behaves differently: there the content is unreachable for find in page, tab order and selection, similar to display: none (MDN Web Docs). For collapsible areas that should stay discoverable, HTML offers a fitting counterpart. An element carrying the attribute value until-found is hidden at first but remains reachable for find in page and fragment navigation; when the browser hits a match it fires a beforematch event, removes the attribute and scrolls to the spot (MDN Web Docs).
<section class="faq-answer" hidden="until-found" id="shipping">
<p>This answer stays discoverable for find in page
even though it is collapsed.</p>
</section>Keep anchor jumps clean
content-visibility: auto are the target of anchor navigation, the jump targets deserve a second look. As long as the placeholder height is roughly right, the jump lands in the correct place; if it is far off, the target shifts during rendering. A realistic contain-intrinsic-size value plus a matching scroll-margin-top underneath a sticky header resolves the vast majority of these cases.Anti-patterns: where content-visibility hurts
The property is cheap to write and expensive to apply wrongly. A blanket selector across all sections usually achieves less than a handful of targeted rules - and produces side effects that only surface in the field. The following patterns come up regularly in audits and should be avoided.
- Hero and LCP containers: the area in the first screen is rendered anyway. Containment brings no benefit there, but it can delay the LCP candidate or - with a wrong placeholder height - displace it.
- Blanket selectors across the whole DOM: rules on
*,divor everysectioncreate thousands of containment boxes. Bookkeeping for them costs time in itself and can worsen the rendering balance. - Elements with sticky positioning in context: layout and paint containment create a new containing block and stacking context. A
position: stickyelement inside such a box then sticks to the box, not to the viewport. - Containers with deliberately overhanging content: dropdowns, tooltips, drop shadows or overlapping image edges get clipped at the border box by paint containment.
- Short pages without content below the fold: if almost everything sits in the first screen, there is no work to skip. The effort is then out of proportion to the effect.
- Sections without a reliable height estimate: without
contain-intrinsic-size, or without theautoprefix, you trade rendering time for a jumping scrollbar and unstable layout.
Selective beats blanket
Measuring properly: rendering time instead of score comparison
The most common mistake in evaluation is staring at a single aggregated number. A performance score is a weighted average of several metrics; it reacts to network variance, throttling settings and chance. A change that costs or gains two points says little about saved rendering work. Anyone evaluating content-visibility measures the work itself - in the performance panel of the developer tools.
- Record a reference run: identical page, identical throttling (CPU slowdown of four to six times for a realistic mobile picture), cache in the same state.
- Read the summary totals for rendering and painting - those are the buckets containment influences directly.
- Look at the
Recalculate StyleandLayoutentries individually: the number of affected elements and the duration per operation say more than the grand total. - Apply the rule, repeat the run, note the difference - same page, same conditions, at least three runs per variant because of the spread.
- Cross-check stability: watch the scrollbar, jump to anchors, test find in page, verify sticky elements and overhanging content.
- After rollout, watch the field data, because the lab only partially reflects the device mix of real usage.
This order prevents the classic misreading in which a measure is discarded or celebrated because of a fluctuating score. How lab values and field data relate to each other is covered in the article on real user monitoring versus CrUX field data; how to read and prioritize a report in a structured way is shown in the guide to the Lighthouse report. For a methodically clean baseline measurement we use the Lighthouse audit with performance report.
Why the effect is largest on constrained mobile devices
Style and layout calculation is pure CPU work. A current laptop handles it so quickly that saving 200 milliseconds of rendering time barely registers in the lab. On a mid-range phone with markedly lower single-core performance the same work multiplies. That is why the distance between lab and field is particularly large for rendering measures - and why the effect shows up more strongly in mobile field data than in any desktop test.
The figures from the HTTP Archive Web Almanac 2025 support this: for INP the share of good scores is 77 percent on mobile against 97 percent on desktop; the gap narrowed from 23 percentage points in 2024 to 20 percentage points in 2025 but remains substantial (HTTP Archive Web Almanac 2025). For LCP, 62 percent good scores on mobile face 74 percent on desktop, and the share of poor experiences on mobile is nearly double at 13 percent against 7 percent (HTTP Archive Web Almanac 2025).
How it plays into the Core Web Vitals
The approach: measure, apply selectively, verify in the field
A three-step approach has proven itself in projects and needs no template rewrite. First the inventory: which templates are long enough for skipping to pay off? As a rule those are category and search result pages, long landing pages, documentation and knowledge trails as well as blog overviews. Then the measurement of rendering and painting totals per template under throttling. Only after that comes the selective application to the repeating sections, accompanied by a visual check.
A typical pattern from practice: a category page with 96 tiles in four row blocks shows around 410 milliseconds of rendering and painting work on initial load under four times CPU throttling. After applying content-visibility: auto with contain-intrinsic-size: auto 460px to the row blocks below the fold, the value falls to roughly 190 milliseconds without removing a single tile or trimming a feature (project experience). Scroll height stays stable because the placeholder height was derived from the median rendered row height. Starting positions like this occur across templates and sectors, among them Shopware performance optimization.
- Identify repeating sections instead of spreading rules across the whole DOM
- Explicitly exclude hero and LCP containers
- Derive the placeholder height per section type from measured heights, preferring the
autoprefix - Verify sticky elements, dropdowns, tooltips and overhanging image edges
- Test find in page, tab order and anchor navigation after the change
- Compare rendering and painting totals before and after under identical throttling
- Observe field values for LCP, INP and CLS over several weeks before widening the rule
One final point concerns durability. Templates grow, sections move, new modules arrive - and a placeholder height that once fitted may no longer match after a redesign. Checking the rendering totals therefore belongs in the same routine as monitoring bundle size. Keeping an eye on the cost of embedded third-party systems as well - for instance the influence of consent banners on LCP - keeps the rendering balance of a long page stable across releases.
We analyse long catalogue, listing and landing page templates for their actual rendering load, apply content-visibility and containment precisely where they work, secure the placeholder heights against new layout shifts and verify the outcome in field data. An overview of the full scope is given on our performance services page; for the concrete implementation on the front end the route leads via frontend optimization with analysis, implementation and re-measurement.
Sources and studies
auto the element gains layout, style and paint containment and skips style, layout and paint work while it sits outside the visible area (MDN Web Docs). In the Chrome documentation demo, rendering time on initial load fell from 232 to 30 milliseconds as a result (web.dev).contain-intrinsic-size supplies a placeholder height; the notation with a leading auto lets the browser remember the size it last rendered and improves the estimate on its own as scrolling continues.content-visibility: auto, yes. The skipped content stays in the Document Object Model and the accessibility tree, remains focusable, selectable, part of the tab order and reachable for find in page (MDN Web Docs). With content-visibility: hidden that does not apply - there the content behaves similarly to display: none. For collapsed but discoverable areas the HTML attribute with the value until-found is the suitable choice.position: sticky is meant to stick to the viewport or where content deliberately extends past the edge, since layout and paint containment form a new containing block and clip the overhang.Recalculate Style and Layout entries before and after the change - under identical CPU throttling and across several runs. Confirmation then belongs in the field data, because the effect shows up more clearly on lower-powered mobile devices than in the lab.