Skip to main content

Duck Lazy

Lazy-loading components and images for React. Built on IntersectionObserver. SSR-safe. Zero dependencies.

Viewport-aware

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.

Become a Sponsor