Question and Suitable Scenarios
You own a long list, article feed, or admin workspace. The DOM contains hundreds of content sections; only a few cards are visible initially, yet the browser still performs style, layout, and paint work for off-screen subtrees. The interview asks you to reduce main-thread rendering work with CSS containment while preserving find-in-page, focus, and screen-reader access.
Assume that the page can be split into independent cards or sections, their heights vary but are not unbounded, and target browsers support content-visibility: auto. Unsupported browsers must still render the page correctly.
What the Interviewer Is Evaluating
- Whether you separate network, script, and rendering bottlenecks before optimizing.
- Whether you can explain the layout, style, and paint containment implied by
auto, plus size containment off screen. - Whether you anticipate placeholder-size errors that create scrollbar jumps and CLS risk.
- Whether you validate performance together with focus, find-in-page, screen-reader, and DOM-read behavior.
A weak answer gives one CSS declaration. A strong answer states the boundary, sizing strategy, cost of forced layout reads, and fallback plan.
Questions to Clarify Before Answering
- Does the slowdown occur at first render, while scrolling, after filtering, or after a click? The phase determines whether you measure rendering, script, or network work.
- Are card heights stable? Larger variance increases the value of real measurements or
contain-intrinsic-size: autoremembering rendered sizes. - Must off-screen content remain searchable, focusable, and exposed to assistive technology? If so,
hiddenis not a drop-in replacement fordisplay: none. - Does code read
offsetHeightorgetBoundingClientRect()during every scroll or state update? Such reads can pull skipped rendering work back into the critical path.
30-Second Answer Framework
“I would first use the Performance panel to confirm that rendering off-screen subtrees is the bottleneck. I would split the feed into independent sections, apply content-visibility: auto to non-critical sections, and provide a realistic contain-intrinsic-size so size containment does not make them look empty. Then I would test focus, find-in-page, and assistive technology behavior, and audit DOM reads that force layout. Finally, I would compare first render, scrolling, INP, CLS, and the unsupported-property fallback against a control.”
Step-by-Step Deep Answer
1. Establish rendering boundaries
Split the long page into independent sections or cards. A layout change inside one boundary should not affect unrelated regions; otherwise containment can hide a real dependency and produce incorrect layout.
.story {
content-visibility: auto;
contain-intrinsic-size: auto 720px;
}When a section is far from the viewport, auto lets the browser skip parts of descendant style, layout, and paint work; as it approaches the viewport, the browser renders it on demand. The DOM remains present.
2. Provide a size placeholder
An off-screen section is temporarily sized without examining its contents. Without an explicit height or intrinsic size, it can look like a very short empty box, changing scrollbar length and the user’s scroll position.
contain-intrinsic-size: auto 720px supplies an initial estimate. After rendering, the browser can remember the real size. Derive the estimate from production samples rather than choosing a decorative number. For large variance, bucket content types or provide a size hint with the data.
3. Distinguish auto, hidden, and display none
auto: skips off-screen rendering and resumes near the viewport; content remains in the DOM and accessibility tree.hidden: keeps rendering state while always skipping rendering; it suits an inactive view, not every accessibility-hiding need.display: none: removes layout and rendering state, so showing it requires rebuilding that state.
If content should be invisible to assistive technology, use semantically correct aria-hidden or remove it from the DOM, and ensure focus cannot enter the hidden region.
4. Audit reads that defeat the optimization
Frequent layout reads on a content-visibility section can force the browser to calculate the skipped subtree early. Measure only when needed, batch reads before writes, and avoid alternating reads and writes that trigger synchronous layout.
requestAnimationFrame(() => {
const height = card.getBoundingClientRect().height;
card.style.setProperty('--measured-height', `${height}px`);
});This illustrates timing, not a universal recipe. Use a Performance recording to prove that a read creates a long task before removing it.
5. Verify with user-facing metrics
At minimum, test:
- First render and total rendering time, to prove off-screen work was reduced.
- INP or click-time long tasks, to see whether the main thread gained headroom.
- CLS and scroll position, to catch placeholder-size jumps.
- Keyboard Tab, find-in-page, and a screen reader, to verify
autoaccessibility behavior. - An unsupported browser, to ensure the default
visiblebehavior still renders all content.
The web.dev example reduced a particular page’s rendering from 232ms to 30ms. Treat that as an experiment result, not a promise for every site; your conclusion must come from your own control and treatment measurements.
High-Quality Sample Answer
I would define the symptom as excessive rendering work for off-screen content, then confirm in the Performance panel that style, layout, or paint dominates the main thread. After confirmation, I would split the page into independent sections, set content-visibility: auto, and estimate contain-intrinsic-size from representative content. The browser can then skip off-screen descendant rendering while keeping the DOM and assistive-technology access intact.
I would not stop at first-render time. I would check scrollbar movement, focus, and find-in-page, and search for getBoundingClientRect or offsetHeight reads that force layout during scrolling or state updates. I would compare first render, scroll long tasks, INP, CLS, and real-user data. If card heights vary wildly or boundaries have cross-section layout dependencies, I would revise the split and sizing strategy. Unsupported browsers get the default visible behavior, so the optimization remains progressive enhancement.
Common Mistakes
- Mistake → Add
content-visibility: autoto the whole page → Why it fails → unclear boundaries hide layout dependencies and make attribution impossible → Fix → split independent sections and record a baseline first. - Mistake → Omit intrinsic sizing → Why it fails → size containment can underestimate section height, worsening scroll and CLS → Fix → estimate from samples and observe real scroll position.
- Mistake → Use
hiddenas a synonym foraria-hidden→ Why it fails → visual hiding and accessibility semantics differ → Fix → choose DOM removal,aria-hidden, or preserved content according to product semantics. - Mistake → Delete every performance-related DOM read → Why it fails → some measurements are required and blind deletion breaks behavior → Fix → use a recording to identify reads that actually force layout.
Follow-Up Questions and Responses
Would you use one intrinsic size when card heights vary by five times?
No. One estimate would make some cards dramatically too short or too tall. I would bucket content types, prefer remembered rendered sizes, and, if needed, return size hints from the server. I would use CLS and scroll error to decide whether the extra bucketing complexity pays off.
Is content-visibility enough if product requires off-screen video decoding to stop completely?
No. It primarily controls rendering work and does not replace media lifecycle management. I would pause and resume video when visibility changes, make sure that logic does not repeatedly read skipped-subtree layout, and measure the media policy separately from the CSS optimization.
How would you ship to browsers that do not support the property?
I would not make functionality depend on it. The default is visible, so the page remains complete; progressive enhancement and compatibility monitoring can show whether older browsers need pagination or a virtual list instead.
How do you prove the gain came from this property rather than a smaller DOM?
Keep the same data and DOM structure and switch only the CSS property in a local or A/B control. Record rendering time, long tasks, INP, and CLS. If pagination, image lazy loading, or script scheduling also changed, the result cannot be attributed to one property.