Lazy Load
shadcn-htmx/lazy-loadFreeComponent
A deferred-content container that fetches its own contents after the page paints (hx-trigger="load") and swaps them in, with a reserved-space placeholder to prevent layout shift (CLS). Pairs with Skeleton for slow dashboard panels and per-tab content. Zero JS of its own — htmx owns the request and the IntersectionObserver.
Live preview
live · rendered by the registry
Rendered by shadcn-htmx on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://shadcn-htmx.productdevbook.com/r/lazy-load.jsonSource
1/** @jsxImportSource hono/jsx */2import type { PropsWithChildren } from "hono/jsx"3import { cn, type ClassValue } from "@/registry/lib/cn"45// Lazy Load — shadcn-htmx, htmx v4 + Tailwind v4.6//7// A deferred-content container. It renders a placeholder immediately, then8// fetches its own contents after the page paints and swaps them in. The9// placeholder reserves vertical space so the swap does not push the page10// around (Cumulative Layout Shift). Pair it with <Skeleton> for slow11// dashboard panels or per-tab content that you don't want to block first12// paint on.13//14// shadcn/ui has no "lazy load" widget — it is a hypermedia loading pattern,15// not a Radix primitive, so there is no React source of truth to mirror. We16// build it straight from the htmx v4 lazy-load pattern and the platform docs:17// repos/htmx/www/src/content/patterns/01-loading/03-lazy-load.md18// (the canonical pattern: a placeholder div with hx-get + hx-trigger="load";19// htmx swaps the response in when it arrives. The "Layout shift" note20// says to reserve space with min-height to protect the Lighthouse/CLS21// score — that is exactly what `reserve`/min-height does here. The22// "Infinite loops" note warns against echoing hx-trigger="load" in the23// response: our default hx-swap="innerHTML" keeps the trigger host in24// place, so the response body must NOT repeat the trigger.)25// repos/htmx/www/src/content/reference/01-attributes/06-hx-trigger.md26// (verified v4: synthetic `load` fires when the element enters the DOM —27// "Useful for lazy-loading content"; `revealed` fires when it scrolls28// into the viewport; use `intersect once` instead when the element lives29// inside an `overflow-y: scroll` container.)30// repos/htmx/www/src/content/reference/01-attributes/07-hx-swap.md31// (verified v4: `innerHTML` — the default — replaces the *contents* of the32// target, leaving our reserved-space wrapper in the DOM; `outerHTML`33// replaces the wrapper wholesale, for when the response brings its own34// box. We default to innerHTML so the reserved height survives the swap.)35// repos/htmx/www/src/content/reference/01-attributes/01-hx-get.md36// (the request the container issues for its own contents.)37// repos/mdn/files/en-us/web/accessibility/aria/reference/attributes/aria-busy/index.md38// (verified: aria-busy="true" on a region tells AT "this content is still39// … truncated
More from shadcn-htmx
All 83 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | shadcn-htmx | Components | Free | no deps | |
| Active Searchactive-search | shadcn-htmx | Components | Free | no deps | |
| Alertalert | shadcn-htmx | Components | Free | no deps | |
| Alert Dialogalert-dialog | shadcn-htmx | Components | Free | no deps | |
| Aspect Ratioaspect-ratio | shadcn-htmx | Components | Free | no deps | |
| Auto Gridauto-grid | shadcn-htmx | Components | Free | no deps | |
| Autocompleteautocomplete | shadcn-htmx | Components | Free | no deps | |
| Autosize Textareaautosize-textarea | shadcn-htmx | Components | Free | no deps |
