React component for lazy loading content using the Intersection Observer API
npx @tessl/cli install tessl/npm-react-lazy-load@4.0.0React Lazy Load is a React component for lazy loading content using the modern Intersection Observer API. It allows developers to defer loading of images and other content until they are about to become visible in the viewport, improving page performance and user experience. The component supports configurable offset margins, visibility thresholds, and custom styling through CSS classes.
npm install react-lazy-loadimport LazyLoad from "react-lazy-load";For CommonJS:
const LazyLoad = require("react-lazy-load");import React from 'react';
import LazyLoad from 'react-lazy-load';
const MyComponent = () => (
<div>
<LazyLoad height={762}>
<img src='https://example.com/image.jpg' alt="Lazy loaded image" />
</LazyLoad>
</div>
);React Lazy Load is built around the Intersection Observer API and consists of:
A React class component that wraps content and defers its rendering until it becomes visible in the viewport.
/**
* React component for lazy loading content using Intersection Observer API
* @param props - Component properties defining behavior and styling
*/
declare class LazyLoad extends React.Component<Props, State> {
static defaultProps: {
elementType: string;
className: string;
offset: number;
threshold: number;
width: null;
onContentVisible: null;
height: null;
};
/** Intersection observer instance used for detecting visibility */
elementObserver: IntersectionObserver | null;
/** React ref to the wrapper element */
wrapper: React.RefObject<React.Component> | null;
constructor(props: Props);
componentDidMount(): void;
shouldComponentUpdate(_: Props, nextState: State): boolean;
componentWillUnmount(): void;
getEventNode(): Window | HTMLElement;
lazyLoadHandler: (entries: IntersectionObserverEntry[]) => void;
render(): React.ReactElement;
}
interface Props {
/** Content to be lazy loaded (required) */
children: React.ReactNode;
/** Additional CSS class names to apply to the wrapper element */
className?: string;
/** HTML element type to render as wrapper (default: 'div') */
elementType?: string;
/** Height of the placeholder element before content loads */
height?: string | number;
/** Viewport offset for triggering load - can be number (pixels) or string (CSS margin format) */
offset?: string | number;
/** Visibility threshold (0-1) - fraction of element that must be visible to trigger loading */
threshold?: number;
/** Width of the placeholder element before content loads */
width?: number | string;
/** Callback function executed when content becomes visible */
onContentVisible?: () => void;
}
interface State {
/** Whether content is visible and should be rendered */
visible: boolean;
}Public methods available on LazyLoad component instances.
/**
* Gets the scroll parent element for the LazyLoad wrapper
* @returns The nearest scrollable ancestor element or window if none found
*/
getEventNode(): Window | HTMLElement;
/**
* Intersection Observer callback handler for visibility detection
* @param entries - Array of intersection observer entries from the browser API
*/
lazyLoadHandler: (entries: IntersectionObserverEntry[]) => void;Method Usage Examples:
import React, { useRef } from 'react';
import LazyLoad from 'react-lazy-load';
const ExampleWithRef = () => {
const lazyLoadRef = useRef<LazyLoad>(null);
const handleClick = () => {
// Access public methods via component ref
if (lazyLoadRef.current) {
const scrollParent = lazyLoadRef.current.getEventNode();
console.log('Scroll parent:', scrollParent);
}
};
return (
<div>
<button onClick={handleClick}>Get Scroll Parent</button>
<LazyLoad ref={lazyLoadRef} height={400}>
<img src="https://example.com/image.jpg" alt="Example" />
</LazyLoad>
</div>
);
};Component Usage Examples:
import React from 'react';
import LazyLoad from 'react-lazy-load';
// Basic image lazy loading
const BasicExample = () => (
<LazyLoad height={400}>
<img src="https://example.com/large-image.jpg" alt="Description" />
</LazyLoad>
);
// Load with 300px offset before visible
const OffsetExample = () => (
<LazyLoad height={400} offset={300}>
<img src="https://example.com/image.jpg" alt="Description" />
</LazyLoad>
);
// Load only when 95% visible with callback
const ThresholdExample = () => (
<LazyLoad
height={400}
width={600}
threshold={0.95}
onContentVisible={() => console.log('Image loaded!')}
>
<img src="https://example.com/image.jpg" alt="Description" />
</LazyLoad>
);
// Custom wrapper element and styling
const CustomWrapperExample = () => (
<LazyLoad
elementType="section"
className="custom-lazy-wrapper"
height={300}
>
<div>
<h3>Lazy loaded content</h3>
<p>This content loads when it becomes visible.</p>
</div>
</LazyLoad>
);The component applies CSS classes automatically for styling and transitions.
/* Base class applied to all LazyLoad wrapper elements */
.LazyLoad {
/* Custom styles here */
}
/* Added when content becomes visible */
.LazyLoad.is-visible {
/* Visible state styles here */
}
/* Example transition effect */
.LazyLoad {
opacity: 0;
transition: all 1s ease-in-out;
}
.LazyLoad.is-visible {
opacity: 1;
}The offset prop controls when loading is triggered relative to the viewport:
// Number: pixels offset in all directions
<LazyLoad offset={100}>Content</LazyLoad>
// String: CSS margin format (top right bottom left)
<LazyLoad offset="100px 0px 200px 50px">Content</LazyLoad>
// String: Single value for all sides
<LazyLoad offset="150px">Content</LazyLoad>The threshold prop controls how much of the element must be visible:
// 0: Load as soon as any part is visible (default)
<LazyLoad threshold={0}>Content</LazyLoad>
// 0.5: Load when 50% is visible
<LazyLoad threshold={0.5}>Content</LazyLoad>
// 1.0: Load only when completely visible
<LazyLoad threshold={1.0}>Content</LazyLoad>Note: When using threshold values > 0, you must specify both width and height props for the browser to calculate the viewable area correctly.
Customize the wrapper HTML element:
// Default div wrapper
<LazyLoad>Content</LazyLoad>
// Custom element types
<LazyLoad elementType="section">Content</LazyLoad>
<LazyLoad elementType="article">Content</LazyLoad>
<LazyLoad elementType="span">Content</LazyLoad>The component gracefully handles various scenarios: