React lazy loading with react-lazyload — guide & best practices
If you want to reduce initial bundle work, avoid rendering offscreen elements, and speed up perceived load time — you need lazy loading. This guide focuses on the popular react-lazyload approach (plus modern alternatives), showing installation, examples for images and components, viewport detection patterns, and performance tips you can apply today.
We’ll cover practical code, explain why you’d prefer react-lazyload or the native IntersectionObserver, and point out traps that cause layout shifts or broken SSR. No fluff, a little sarcasm, and lots of actionable advice.
Quick links: react-lazyload npm · react-lazyload GitHub · React lazy loading (React.lazy & Suspense) · Intersection Observer docs · react-lazyload tutorial (dev.to).
How react-lazyload works (and what it does for you)
react-lazyload is a React component wrapper that defers rendering of its children until they enter the viewport (or within a configurable offset). Internally it listens to scroll/resize events or uses the browser’s IntersectionObserver when available. That means the DOM nodes, images or heavy components aren’t created until they’re about to be shown — saving CPU, memory and paint work.
It’s not magic: react-lazyload mounts and renders children only when necessary. For images that can dramatically reduce the number of bytes requested upfront, and for lists or carousels it lowers the number of mounted React components. The net result: faster Time to Interactive and less jank.
However, lazy loading is not a silver bullet. Misconfigured lazy loading can cause layout jumps, delayed resource loads (visible image pop-in), or interaction latency if you lazy-load interactive components that should be ready immediately. We’ll cover mitigations below.
Installation & basic setup
Install the package with npm or yarn. Use the link below for the latest version and release notes:
npm install react-lazyload or yarn add react-lazyload. See the react-lazyload installation page for version details.
Basic import and usage:
import LazyLoad from 'react-lazyload';
<HeavyComponent />
The wrapper tells react-lazyload the approximate height to reserve for the child (helps avoid layout shift). The offset prop instructs the component to start loading before the element actually enters the viewport — good for smoothness on slow networks.
Practical examples — images, components and IntersectionObserver fallback
Example: lazy-load an image with a lightweight placeholder. This prevents the browser from fetching the full-size image until it’s near view.
import LazyLoad from 'react-lazyload';
function Avatar() {
return (
<LazyLoad height={150} offset={100} once placeholder=<div className="avatar-placeholder">…</div>>
<img src="/avatars/large.jpg" alt="User avatar" width="150" height="150" />
</LazyLoad>
);
}
For components (code-splitting + render deferral) combine React.lazy/Suspense with visual placeholders. React.lazy handles module downloading; react-lazyload controls DOM mounting. Use both where appropriate.
// Code-splitting + mount control
const HeavyWidget = React.lazy(() => import('./HeavyWidget'));
<LazyLoad height={400} offset={200} once>
<Suspense fallback=<Spinner />>
<HeavyWidget />
</Suspense>
</LazyLoad>
If you prefer a modern approach without additional wrappers, implement lazy loading directly with the Intersection Observer API or use light wrappers like react-intersection-observer. That approach gives you finer control and fewer dependencies.
Example: tiny Intersection Observer image hook (concept):
function useInView(ref, options) {
// returns boolean inView; uses IntersectionObserver internally
}
Common props and configuration (quick reference)
The most useful <LazyLoad /> props are:
- height — approximate height to reserve to avoid layout jump
- offset — start loading X pixels before element enters viewport
- once — load only once (do not unmount when scrolled away)
- placeholder — element shown until children are mounted
Set sensible defaults for lists and images. Height-less children can cause cumulative layout shift; if you can’t set height, set a CSS aspect-ratio or placeholder size.
Performance tips and pitfalls (what actually moves the needle)
Lazy loading improves perceived performance, but to make it reliable you need to consider network, layout and interaction. The biggest wins come from deferring heavy images and components that are clearly below-the-fold. Use the following checklist.
- Reserve space: provide height or aspect-ratio to prevent layout shifts.
- Use placeholders: low-res blurred or skeletons reduce perceived loading time.
- Avoid lazy-loading critical UI: nave bars, above-the-fold CTAs or UI that should be instantly interactive must be rendered immediately.
Other caveats: server-side rendering (SSR). react-lazyload mounts children client-side, so on SSR the content may be missing until hydration. If SEO requires server-rendered content, either server-render the above-the-fold content or avoid lazy-loading critical SEO assets.
Finally, measure. Use Lighthouse, Real User Monitoring (RUM) or Chrome DevTools to validate improvements in First Contentful Paint (FCP), Largest Contentful Paint (LCP) and Time to Interactive (TTI).
React intersection observer vs react-lazyload — choose wisely
Both strategies detect when elements enter the viewport. react-lazyload provides a convenient wrapper with features like offsets and placeholders out of the box. Intersection Observer (native) is lower-level and usually more efficient if you implement batching and reuse observers.
If you want minimal dependencies and maximum control — implement a simple Intersection Observer hook. If you want quick results and built-in edge-case handling (offsets, placeholders, once semantics) — react-lazyload is practical.
Browser support is solid for IntersectionObserver in modern browsers; for legacy browsers you can include a polyfill. react-lazyload also gracefully falls back to scroll/resize events when IntersectionObserver is not present.
Accessibility and SEO considerations
Lazy loading images using <img loading="lazy"> is supported in most modern browsers and requires no JS — great for simple cases. But if you need placeholders, low-res previews, or complex mount logic, JS-based lazy loading gives more control.
For SEO-critical content, prefer server rendering or ensure that content appears in the initial HTML. Search engines have improved crawling of JS-rendered content, but it’s safer to avoid lazy-loading content that search engines must index.
Always keep semantic markup and alt attributes for images. Lazy-loading should not remove essential semantics or break keyboard navigation — ensure interactive components are focusable or preloaded if user interaction is expected immediately.
Conclusion — when to use react-lazyload
Use react-lazyload when you need a quick, configurable wrapper to defer rendering of below-the-fold elements and you value convenience over the tiny bundle size cost of a dependency. Combine it with React.lazy for component code-splitting when both DOM mount and module download should be deferred.
If you want the smallest possible runtime and the most control, use the Intersection Observer API (or a small hook library). If you need polished behavior fast — react-lazyload is a pragmatic choice.
Measure before and after. Lazy loading is easy to misconfigure: when done right you reduce wasted rendering and bandwidth; when done wrong you increase layout shift and interaction latency.
FAQ
- What is react-lazyload and how does it work?
- react-lazyload is a React wrapper component that defers rendering of its children until they approach the viewport. It uses IntersectionObserver when available and falls back to scroll/resize listeners otherwise, conserving CPU, memory and network requests.
- How do I lazy load images in React?
- Use native
loading="lazy"for simple cases. For more control, wrap images in<LazyLoad />or use IntersectionObserver to swap src when the element enters view. Always provide width/height or aspect-ratio to avoid layout shifts. - Should I use react-lazyload or IntersectionObserver directly?
- Use react-lazyload for quick, feature-rich lazy loading (offsets, placeholders, once). Use IntersectionObserver directly if you need minimal dependencies and fine-grained control.
Semantic core (keyword clusters)
Main keywords
react-lazyload
react lazy loading
react-lazyload tutorial
react-lazyload installation
react-lazyload example
react-lazyload setup
react-lazyload images
react-lazyload performance
react-lazyload getting started
Supporting & intent-driven keywords
React image lazy load
React lazy load component
React viewport detection
React intersection observer
React lazy loading images
React performance optimization
react-lazyload example usage
react-lazyload props offset height placeholder
lazy load images react tutorial
IntersectionObserver React hook
code splitting React.lazy Suspense
SSR and lazy loading
LSI / related phrases (long-tail)
deferred loading
lazy image loading
below-the-fold content
lazy loading best practices
prevent layout shift lazy load
lazy load placeholder skeleton
native lazy loading loading="lazy"
react-lazyload vs intersection observer
optimize LCP with lazy loading
Clusters by intent
- Informational:
React lazy loading, React intersection observer, React viewport detection, React performance optimization
- Transactional / Setup:
react-lazyload installation, react-lazyload setup, react-lazyload getting started
- How-to / Tutorial:
react-lazyload tutorial, react-lazyload example, React image lazy load, React lazy load component
- Comparative:
react-lazyload performance, react-lazyload vs intersection observer, React.lazy vs react-lazyload
Outbound references (quick)
Useful authoritative links (anchor text uses target keywords):

