In modern web development, performance is key to delivering a smooth user experience. One common performance issue is slow image loading, especially when a page contains many images.
In this blog, we’ll explore how to tackle this problem using the react-lazy-load-image-component library, which can significantly enhance your application’s loading speed and overall user experience.
The Problem: Slow Image Loading
When a webpage includes many images, loading all of them at once can slow down the page, leading to a poor user experience. Images that are not immediately visible to the user add unnecessary load time and can affect the page’s performance. This is where lazy loading becomes essential.
What is Lazy Loading?
Lazy loading is a technique where images (or other resources) are loaded only when they come into the viewport. This means that images that are off-screen won’t be loaded until the user scrolls down to them, which reduces initial load time and saves bandwidth.
Introducing React Lazy Load Image Component
The react-lazy-load-image-component library is a powerful tool that simplifies lazy loading of images in React applications. It provides an easy-to-use Lazy Load Image component that supports various features like blur-up placeholders, responsive images, and more.
Setting Up Your React Application
Let’s dive into an example to understand how to use this library effectively. We’ll use it to build a cake product page where images are loaded lazily.
Installation
To get started, you need to install the library:
npm i react-lazy-load-image-component
Oher necessary packages (Optional):
npm install react-grid-system styled-components
Creating the Product Page Component
The Cake ProductPage component displays a gallery of images using a responsive grid layout. Here’s the code:
ProductPage.jsx
// Import Library import React from "react"; import { Container, Row, Col } from "react-grid-system"; // Import Component import Card from "./Card"; // Import Images import Cake1 from "../images/Cake1.jpg"; import Cake2 from "../images/Cake2.jpg"; import Cake3 from "../images/Cake3.jpg"; import Cake4 from "../images/Cake4.jpg"; import Cake5 from "../images/Cake5.jpg"; import Cake6 from "../images/Cake6.jpg"; import Cake7 from "../images/Cake7.jpg"; import Cake8 from "../images/Cake8.jpg"; import Cake9 from "../images/Cake9.jpg"; import Cake10 from "../images/Cake10.jpg"; import Cake11 from "../images/Cake11.jpg"; import Cake12 from "../images/Cake12.jpg"; import Cake13 from "../images/Cake13.jpg"; import Cake14 from "../images/Cake14.jpg"; import Cake15 from "../images/Cake15.jpg"; import Cake17 from "../images/Cake17.jpg"; import Cake18 from "../images/Cake18.jpg"; import Cake1PPlaceholderImg from "../images/Cake1PPlaceholderImg.jpg"; import Cake2PPlaceholderImg from "../images/Cake2PPlaceholderImg.jpg"; import Cake3PPlaceholderImg from "../images/Cake3PPlaceholderImg.jpg"; import Cake4PPlaceholderImg from "../images/Cake4PPlaceholderImg.jpg"; import Cake5PPlaceholderImg from "../images/Cake5PPlaceholderImg.jpg"; import Cake6PPlaceholderImg from "../images/Cake6PPlaceholderImg.jpg"; import Cake7PPlaceholderImg from "../images/Cake7PPlaceholderImg.jpg"; import Cake8PPlaceholderImg from "../images/Cake8PPlaceholderImg.jpg"; import Cake9PPlaceholderImg from "../images/Cake9PPlaceholderImg.jpg"; import Cake10PPlaceholderImg from "../images/Cake10PPlaceholderImg.jpg"; import Cake11PPlaceholderImg from "../images/Cake11PPlaceholderImg.jpg"; import Cake12PPlaceholderImg from "../images/Cake12PPlaceholderImg.jpg"; import Cake13PPlaceholderImg from "../images/Cake13PPlaceholderImg.jpg"; import Cake14PPlaceholderImg from "../images/Cake14PPlaceholderImg.jpg"; import Cake15PPlaceholderImg from "../images/Cake15PPlaceholderImg.jpg"; import Cake17PPlaceholderImg from "../images/Cake17PPlaceholderImg.jpg"; import Cake18PPlaceholderImg from "../images/Cake18PPlaceholderImg.jpg"; const ProductPage = () => { return ( <div> <Container> <Row> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake1} placeholderImg={Cake1PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake2} placeholderImg={Cake2PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake3} placeholderImg={Cake3PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> </Row> <Row> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake4} placeholderImg={Cake4PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake5} placeholderImg={Cake5PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake6} placeholderImg={Cake6PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> </Row> <Row> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake7} placeholderImg={Cake7PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake8} placeholderImg={Cake8PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake9} placeholderImg={Cake9PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> </Row> <Row> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake10} placeholderImg={Cake10PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake11} placeholderImg={Cake11PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake12} placeholderImg={Cake12PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> </Row> <Row> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake13} placeholderImg={Cake13PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake14} placeholderImg={Cake14PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake15} placeholderImg={Cake15PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> </Row> <Row> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake2} placeholderImg={Cake2PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake17} placeholderImg={Cake17PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> <Col xs={4} sm={4} md={4} lg={4} xl={4}> <Card image={Cake18} placeholderImg={Cake18PPlaceholderImg} title="Card Title" description="This is a description of the card. It can be a few lines long." /> </Col> </Row> </Container> </div> ); }; export default ProductPage;
Creating the Card Component
Create a Card component where images will be displayed. Here’s how you can set it up:
Card.jsx
// Import Library import React, { useState } from "react"; import styled, { keyframes } from "styled-components"; import { LazyLoadImage } from "react-lazy-load-image-component"; // CSS Imports import "react-lazy-load-image-component/src/effects/blur.css"; const CardContainer = styled.div` border: 1px solid #e0e0e0; border-radius: 8px; overflow: hidden; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); max-width: 300px; text-align: center; margin-bottom: 50px; margin-top: 50px; `; const shimmer = keyframes` 0% { background-position: -468px 0; } 100% { background-position: 468px 0; } `; const ShimmerWrapper = styled.div` background: #f6f7f8; background-image: linear-gradient( to right, #f6f7f8 0%, #edeef1 20%, #f6f7f8 40%, #f6f7f8 100% ); background-repeat: no-repeat; background-size: 800px 200px; position: absolute; top: 0; left: 0; width: 100%; height: 100%; animation: ${shimmer} 1s linear infinite; `; const ImageWrapper = styled.div` position: relative; width: 100%; max-height: 200px; `; const Image = styled(LazyLoadImage)` width: 100%; height: 100%; object-fit: cover; background-color: #f0f0f0; opacity: ${({ isLoaded }) => (isLoaded ? 1 : 1)}; transition: opacity 0.5s ease; position: absolute; top: 0; left: 0; `; const Title = styled.h2` font-size: 1.5rem; margin: 16px 0 8px; `; const Description = styled.p` font-size: 1rem; color: #666; padding: 0 16px; margin-bottom: 16px; `; const Button = styled.button` background-color: #ff7d29; color: #fff; border: none; border-radius: 4px; padding: 10px 20px; margin-bottom: 16px; cursor: pointer; transition: background-color 0.3s ease; &:hover { background-color: #c9631f; } `; const Card = ({ image, title, description, placeholderImg }) => { const [isLoaded, setIsLoaded] = useState(false); return ( <CardContainer> <ImageWrapper> {!isLoaded && <ShimmerWrapper />} <Image src={image} effect="blur" alt={title} placeholderSrc={placeholderImg} width={300} height={200} useIntersectionObserver={true} onLoad={() => setIsLoaded(true)} isLoaded={isLoaded} /> </ImageWrapper> <Title>{title}</Title> <Description>{description}</Description> <Button>Learn More</Button> </CardContainer> ); }; export default Card;
Explanation
Styled Components: We use styled-components to style our card. The CardContainer provides a border, shadow, and margin, while ImageWrapper and ShimmerWrapper manage image placeholders.
LazyLoadImage: The LazyLoadImage component from react-lazy-load-image-component is used to render the image.
It supports a placeholderSrc prop for the image that will be shown while the actual image is loading. The effect prop with the value “blur” adds a blur effect to the placeholder image.
Shimmer Effect: The shimmer effect is applied using CSS animations, giving users a visual indication that content is loading.
State Management: The useState hook is used to track whether the image has loaded. We show the shimmer effect until the image is fully loaded.
Setting Up the Main Application
In your App component, import and render the ProductPage component:
App.jsx
import './App.css'; import ProductPage from './components/ProductPage'; function App() { return ( <> <ProductPage /> </> ); } export default App;
Ensure you have a global CSS file for basic styles, including font imports:
App.css
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); body { font-family: "Poppins", sans-serif }
Output:
Conclusion
By implementing lazy loading with react-lazy-load-image-component, you can significantly enhance the performance of image-heavy applications, ensuring a smoother and faster user experience.
Feel free to adapt this approach to your own projects, and remember that efficient image handling is just one aspect of creating high-performing web applications.
Add comment