content-visibility: auto

Skip rendering offscreen content until the user scrolls to it — the browser does the lazy-rendering automatically. Two CSS properties replace IntersectionObserver boilerplate entirely.

1. Long List — 1000 items with content-visibility: auto

1000 list-group items rendered with content-visibility: auto; contain-intrinsic-size: auto 60px. Scroll down — offscreen items skip rendering until visible. Render time measured with Performance API.

2. Heavy Card Grid — 100 cards with content-visibility: auto

100 cards with text content. Each card uses content-visibility: auto; contain-intrinsic-size: auto 400px. Offscreen cards skip layout/paint entirely.

3. Code Comparison — IntersectionObserver vs content-visibility

JS: IntersectionObserver
// Create observer
const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        entry.target.classList
          .add('visible');
        renderContent(entry.target);
        observer.unobserve(entry.target);
      }
    });
  },
  { rootMargin: '100px' }
);

// Observe all items
document.querySelectorAll('.lazy-item')
  .forEach(item => {
    observer.observe(item);
  });

// Render function
function renderContent(el) {
  el.innerHTML = buildContent();
  el.style.minHeight = '';
}

// Cleanup on page unload
window.addEventListener('unload', () => {
  observer.disconnect();
});
CSS: content-visibility
/* That's it. Two CSS properties. */
.item {
  content-visibility: auto;
  contain-intrinsic-size: auto 60px;
}

/* The browser automatically:
   - Skips layout for offscreen items
   - Skips paint for offscreen items
   - Renders when scrolled into view
   - Preserves scrollbar stability
   - No JS, no observer, no cleanup */

4. Performance Metrics

Generate both lists above to see measured render times. content-visibility: auto reduces initial paint because offscreen elements are skipped.

Test Items DOM Insert Time CSS Applied
Long List 1000 content-visibility: auto
Card Grid 100 content-visibility: auto
Implementation: content-visibility (key code)
<style>
  .list-item {
    content-visibility: auto;
    contain-intrinsic-size: auto 60px;
  }
  .card-item {
    content-visibility: auto;
    contain-intrinsic-size: auto 400px;
  }
</style>

<!-- Just add the class. No JS needed. -->
<div class="list-item">...</div>
<div class="card-item">...</div>

<!-- The browser automatically skips rendering
     for offscreen elements until they scroll
     into view. Scrollbar stays stable thanks
     to contain-intrinsic-size. -->