Duck Lazy
Lazy-loading components and images for React. Built on IntersectionObserver. SSR-safe. Zero dependencies.
Render only what the user can see
Defer components and images until they scroll into view. Smaller initial HTML, faster first paint, cheaper hydration.
IntersectionObserver
Defers rendering until the wrapper enters the viewport. Takes the native observer `rootMargin` and `threshold` options.
DuckLazyComponent
Wrap any subtree. Children mount when the wrapper intersects the viewport. A placeholder slot renders until then.
DuckLazyImage
Lazy `<img>` that swaps the placeholder on load. Configurable fade transition, preserved aspect ratio.
next/image friendly
Use `DuckLazyImage` inside a Next.js app, or pass any image element as a child. No framework coupling.
Zero dependencies
Pure React plus the browser IntersectionObserver API. No polyfills, no extra weight.
SSR-safe
Renders the placeholder on the server and upgrades on the client once the observer fires. No hydration mismatches.
Install
Wrap the parts of your tree that live below the fold.
# Install
bun add @gentleduck/lazy
# Lazy mount a subtree
import { DuckLazyComponent } from '@gentleduck/lazy/lazy-component'Free & open source
gentleduck is MIT licensed and will always be free and open source. Every package ships with full source access — fork it, modify it, own it.