How to Create a Skeleton Loader Component in React
In today’s fast-paced web applications, user experience is key. One way to improve perceived performance is by showing skeleton loaders—those grey placeholders that simulate the layout of content while it’s being fetched. They let users know that data is on its way and improve the perceived loading speed of your app.
In this blog post, we’ll explore how to create a Skeleton Loader Component in React from scratch. We’ll also go over some use cases where skeleton loaders come in handy and look at the benefits of using them in your React projects.
What is a Skeleton Loader?
A skeleton loader is a placeholder UI that mimics the shape and layout of your actual content before it's loaded. Instead of showing a loading spinner or blank screen, you provide greyed-out shapes to indicate where images, text, and other elements will be displayed once the content is fetched.
This technique has become a popular alternative to traditional loading indicators, as it reduces the sudden shift between empty states and fully rendered content.
Why Use Skeleton Loaders?
Improves UX: Users are visually informed that the content is being loaded, which makes the app feel faster and more responsive.
Reduces Layout Jumps: By providing placeholders that match the final content layout, skeleton loaders reduce the layout shift that can happen when content suddenly appears.
Enhances Perceived Performance: Even if the actual load time is the same, users feel like the app is loading faster when skeleton loaders are used.
Step-by-Step Guide to Creating a Skeleton Loader in React
Let’s create a basic skeleton loader component in React and integrate it with a typical API call.
Step 1: Setting Up a Basic React Project
First, if you haven’t already, create a new React project using Create React App:
npx create-react-app skeleton-loader-demo
cd skeleton-loader-demo
npm start
Now you have a basic React setup ready to go.
Step 2: Creating the Skeleton Loader Component
Let’s build the SkeletonLoader
component, which will render the grey placeholders for text, images, or other content.
Create a new file called SkeletonLoader.js
inside the src
folder:
import React from 'react';
import './SkeletonLoader.css';
const SkeletonLoader = ({ width, height, borderRadius }) => {
return (
<div
className="skeleton-loader"
style={{
width: width || '100%',
height: height || '20px',
borderRadius: borderRadius || '4px',
}}
></div>
);
};
export default SkeletonLoader;
This component accepts width
, height
, and borderRadius
as props, allowing us to customize the size and shape of the skeleton elements. Next, we’ll style this component using basic CSS.
Step 3: Adding Styles for the Skeleton Loader
Create a CSS file called SkeletonLoader.css
in the src
folder:
.skeleton-loader {
background-color: #e0e0e0;
animation: shimmer 1.5s infinite linear;
}
@keyframes shimmer {
0% {
background-position: -100%;
}
100% {
background-position: 100%;
}
}
Here, we’re giving the skeleton a light grey background color and an animated "shimmer" effect that moves from left to right. This effect helps simulate the perception of loading.
Step 4: Using the Skeleton Loader in Your App
Now, let’s use the SkeletonLoader
component to simulate loading in a typical data-fetching scenario.
In your App.js
file, modify the code to simulate an API call and show the skeleton loader while the data is being fetched:
import React, { useEffect, useState } from 'react';
import SkeletonLoader from './SkeletonLoader';
const App = () => {
const [data, setData] = useState(null);
useEffect(() => {
// Simulate an API call
setTimeout(() => {
setData({
title: 'Skeleton Loader in React',
description: 'This is a blog post description.',
imageUrl: 'https://via.placeholder.com/300',
});
}, 3000); // 3-second delay
}, []);
return (
<div className="App">
<h1>Blog Post</h1>
{/* If data is still loading, show skeleton loaders */}
{!data ? (
<div>
<SkeletonLoader width="70%" height="30px" />
<SkeletonLoader width="100%" height="200px" borderRadius="8px" />
<SkeletonLoader width="90%" height="20px" />
<SkeletonLoader width="60%" height="20px" />
</div>
) : (
// Render actual content after data has been fetched
<div>
<h2>{data.title}</h2>
<img src={data.imageUrl} alt={data.title} style={{ width: '300px', borderRadius: '8px' }} />
<p>{data.description}</p>
</div>
)}
</div>
);
};
export default App;
In this example, we’re simulating an API call that fetches a blog post. While the data is being fetched (in this case, a 3-second delay), we display the skeleton loaders. Once the data is available, the actual content is rendered in place of the placeholders.
Step 5: Styling the App
Let’s also add some basic styling for the app. In the src/App.css
file, you can add the following styles:
.App {
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
text-align: center;
}
h2 {
margin-top: 20px;
}
img {
display: block;
margin: 20px 0;
}
This gives the app a basic layout and ensures the skeleton loaders align well with the actual content.
Step 6: Customizing Skeleton Loaders for Different Use Cases
One of the great things about skeleton loaders is their flexibility. Depending on the type of content you’re loading, you can easily adjust the shape and size of the placeholders.
Here are some examples of how you can customize skeleton loaders for different content:
Text: You can create multiple
SkeletonLoader
components with varying widths to simulate paragraphs of text.Images: Use a larger
SkeletonLoader
with specific dimensions to mimic the shape of images.Avatars or Icons: For circular content like avatars, you can set a
borderRadius
of50%
.
For example, if you were loading a user profile with an avatar and bio:
<div>
<SkeletonLoader width="80px" height="80px" borderRadius="50%" /> {/* Avatar */}
<SkeletonLoader width="50%" height="20px" /> {/* Username */}
<SkeletonLoader width="90%" height="20px" /> {/* Bio */}
</div>
Step 7: Benefits of Skeleton Loaders Over Traditional Loading Indicators
Visual Consistency: Skeleton loaders maintain the layout and design of the app, providing users with a better sense of what content to expect. It’s less disruptive than spinners, which don’t inform users about what’s coming next.
Improved Perception of Speed: Users feel like they’re waiting less time when the UI is already somewhat "ready" via placeholders.
Reduced Cognitive Load: Since the layout remains fixed, users can focus on the incoming content rather than adjusting to new layouts.
Conclusion
Skeleton loaders are a simple yet effective way to enhance the user experience of your React applications. By providing placeholders that mimic the layout of your content, they reduce layout shifts and improve perceived performance. The skeleton loader component we built is highly customizable and can be adapted for various content types.
Now that you know how to build and use skeleton loaders, try adding them to your next React project and see how they improve your app’s overall user experience!
Subscribe to my newsletter
Read articles from Mohammed Omar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by