Skip to content
HomePagesHomePages template kit

Use `content-visibility`

Let off-screen sections stop consuming raster memory on a long, image-heavy page — and pay the containment cost deliberately.

A page that stacks many image-heavy sections can exhaust the browser’s GPU/raster memory — enough to make it evict a live WebGL map’s layer on scroll, blanking the map. content-visibility: auto fixes this by letting off-screen sections skip rendering, so they stop consuming that memory.

  • A template whose page stacks several image-heavy sections — Add a second template creates one and adds sections to it.
  • That template’s Tailwind entry, the second stylesheet a published page loads. A scaffolded starter has none; the example workspace ships one — see A skeleton, not a worked example.

The kit does not apply this for you — it has a real cost (below), and only you know whether your page needs it. If it does, add the rule to your Tailwind entry — the second stylesheet the page loads:

@layer template {
.tr-root .tr-section:not(header):not(.my-map-section) {
content-visibility: auto;
contain-intrinsic-size: auto 600px;
}
}

contain-intrinsic-size: auto remembers each section’s rendered height, avoiding scroll jank.

Layer placement matters: inside @layer template, a Tailwind utility (@layer utilities, which comes later in the layer order) can always override this rule on a given section. Left unlayered, it would beat every layer instead, including utilities. Neither collides today — no Tailwind utility sets content-visibility — but wrapping it in @layer template keeps that guarantee explicit rather than accidental.

The cost. content-visibility implies contain: paint, which clips descendants to the section box. So:

  • A full-screen overlay — a lightbox, a gallery, a modal — must be appended to document.body, never rendered inside the section. Inside, it gets clipped.
  • A section that must stay painted while off-screen (a live map), or whose dropdowns escape its box, must be excluded — add its class to the :not() list, as .my-map-section is above.

The CSS fence under Steps is the whole change: one rule, in the template’s Tailwind entry, inside @layer template.

.tr-root is set on <body> at publish time and is absent in the editor, so the rule is published-only — and so are its consequences. You will not see them in preview. Verify the rule itself by reading it, and the rest with the author loop.

None — this guide changes no file check inspects.

  • The CSS pipeline — the two stylesheets a published page loads, and the cascade-layer order they declare.
  • unlayered-fence — why a hand-written rule belongs inside a layer.
  • Islands — interactivity in a section, and the "use client" boundary.