Img Component & Lazy Loading
Use the built-in <Img> component to keep images from blocking initial render. It ships a real <img> tag on the server and lazily swaps in the real source once it nears the viewport — no 'use client' needed in your own file.
Overview
Use the built-in <Img> component for images that shouldn't block initial render. It's a "use client" boundary internally, but you can drop it into a server component like any other tag — no "use client" directive needed in your own file.
import { Img } from 'nukejs'
export default function Gallery() {
return (
<Img
src="/photos/mountain.jpg"
alt="Mountain at sunrise"
width={800}
height={450}
/>
)
}<Img> renders a real <img> tag immediately — width/height reserve the space so there's no jump when the real image loads, and nothing needs to hydrate in later that could flash missing content.How it works
In the browser, the component doesn't set src to the real image right away. Instead it watches itself with IntersectionObserver and only swaps in the real src once the element is about to enter the viewport (controlled by rootMargin, 200px by default). Until then it shows placeholder if you gave it one, or just waits.
Browsers that don't support IntersectionObserver, and the initial server render, always get the real image — the component never hides content it can't guarantee it'll lazily reveal later.
Blurred placeholders
Pass a small/blurred placeholder image and <Img> will show it (with a CSS blur) until the real image finishes loading, then cross-fade:
<Img
src="/photos/mountain-full.jpg"
placeholder="/photos/mountain-tiny.jpg"
alt="Mountain at sunrise"
width={800}
height={450}
/>Loading images eagerly
Lazy loading is wasted (and can even hurt LCP) on above-the-fold images like a hero banner. Set eager to skip the IntersectionObserver step and load immediately:
<Img src="/hero.jpg" alt="Welcome" width={1600} height={600} eager />Props
| Prop | Type | Description |
|---|---|---|
src | string | Image URL — swapped in once the image is near the viewport |
alt | string | Alt text (required) |
width | number | string | Rendered width — set alongside height to prevent layout shift |
height | number | string | Rendered height |
placeholder | string | Low-res/blurred image shown until src loads |
rootMargin | string | How far ahead of the viewport to start loading — passed straight to IntersectionObserver. Default "200px" |
eager | boolean | Skip lazy-loading and load src immediately. Use for above-the-fold images |
className | string | CSS class(es) applied to the underlying <img> |
style | React.CSSProperties | Inline styles merged with the blur transition NukeJS applies internally |
onLoad | (e) => void | Fired when the real image finishes loading |
onError | (e) => void | Fired if the image fails to load |
Sample
See a runnable example with a full gallery, blurred placeholder, and eager hero image on the Img sample page.