The web has recently undergone improvements that benefit both consumers and developers. Because new methods of enhancing user experiences continue to emerge over time, user experience is a major focus that goes beyond present metrics.
Skeleton displays are one component of UX improvement. In this article, we’ll be covering the purpose of skeleton loaders, their significance, and how to create one for a website using React and basic CSS.
What is a Skeleton Screen?
An animated placeholder known as a "skeleton screen" simulates a website's design while data is being loaded. Skeleton screens inform the user that some content is loading while also, and perhaps more crucially, indicating whether an image, text, card or other type of data is loading.
Because the user is aware of the type of content loading before it manifests, the page appears to load more quickly. Perceived performance is what we're talking about here.
Here are some illustrations of skeleton displays from Medium and Facebook:
The gray shapes indicate how the data will be shown once it has loaded. These images are replaced once the data from the server actually arrives.
Skeleton loaders seldom improve efficiency or loading speed. They exist solely to provide the visitor with something to look at and the impression that the website is loading more quickly.
Notable Qualities of Skeleton Loaders
- They seem to move more quickly and are easier to utilize. A better user experience and higher conversion rates are both provided by improved perceived performance.
- They give the impression of quickness and quick loading.
- Users have no indication of what is loading or how long it will take with spinners and loaders, which can be a problem.
- Since the load time is unknown, using spinners or loaders puts the user in a state of uncertainty.
- Users might be tempted to move on rather than wait through skeleton screens.
Build a Skeleton Loader with React
For the purpose of this article's tutorial, we'll build a page that lists blog articles as cards. The final product will resemble the following:
The skeleton screen:
The actual site after loading:
Setting up a React Project
We'll begin by putting up a React project with the code below in order to use Google Charts in our React application:
npx create-react-app react-skeleton
Next, let’s change the working directory to the folder established by the previous command with the following code:
cd react-react-skeleton
Next, we’ll open the folder in our preferred text editor. Now that our app is configured, it's time to add and remove unnecessary boilerplate from it. In the /src
folder, let’s make a components
folder, and in the root directory, we’ll make a server
folder.
We have a server
folder because we're going to create a structure that resembles a database so we can store information about the blogs. We won't be entering any backend, so don't be concerned. With JSON
Server, we’ll create a phony REST API.
Next, let’s create a file named db.json
or data.json
in the /server
folder and fill it with some random information typically found on a blog, such as an avatar, author name, thumbnail, title, and description.
The contents of our db.json
file should resemble something like the image below.
N.B.: An altered version of data is used in this tutorial due to its enormous size, but you can tweak it to your own style as much as you want.
//db.json
{
"blogs" : [
{
"title" : "Using regression testing to produce working software",
"thumbnail" : "https://blog.pieces.com/hero_Z1Aauk4.webp",
"avatar" : "https://blog.pieces.com/authors/avatars/goodness-woke.jpg",
"author" : "Goodness Woke",
"description" : "Lorem ipsum dolor sit amet, consectetur adipisci"
},
{
"title" : "Using regression testing to produce working software",
"thumbnail" : "https://blog.pieces.com/hero_Z1Aauk4.webp",
"avatar" : "https://blog.pieces.com/authors/avatars/goodness-woke.jpg",
"author" : "Goodness Woke",
"description" : "Lorem ipsum dolor sit amet, consectetur adipisci"
},
{
"title" : "Using regression testing to produce working software",
"thumbnail" : "https://blog.pieces.com/hero_Z1Aauk4.webp",
"avatar" : "https://blog.pieces.com/authors/avatars/goodness-woke.jpg",
"author" : "Goodness Woke",
"description" : "Lorem ipsum dolor sit amet, consectetur adipisci"
},
{
"title" : "Using regression testing to produce working software",
"thumbnail" : "https://blog.pieces.com/hero_Z1Aauk4.webp",
"avatar" : "https://blog.pieces.com/authors/avatars/goodness-woke.jpg",
"author" : "Goodness Woke",
"description" : "Lorem ipsum dolor sit amet, consectetur adipisci"
},
{
"title" : "Using regression testing to produce working software",
"thumbnail" : "https://blog.pieces.com/hero_Z1Aauk4.webp",
"avatar" : "https://blog.pieces.com/authors/avatars/goodness-woke.jpg",
"author" : "Goodness Woke",
"description" : "Lorem ipsum dolor sit amet, consectetur adipisci"
},
{
"title" : "Using regression testing to produce working software",
"thumbnail" : "https://blog.pieces.com/hero_Z1Aauk4.webp",
"avatar" : "https://blog.pieces.com/authors/avatars/goodness-woke.jpg",
"author" : "Goodness Woke",
"description" : "Lorem ipsum dolor sit amet, consectetur adipisci"
}
]
}
We need to run the above file using the JSON Server package so that we can add endpoints to it and conduct operations like POST
, GET
, DELETE
, etc.
To do that, let’s open a new terminal and run json-server -watch server/db.json --port 8000
. If it runs successfully, then the terminal should start the server on port 8000, and we should start watching for any changes. By copying and pasting http://localhost:8000 in a browser, we’ll see that the JSON file has been hosted on localhost. We can also see the blog resources on http://localhost:8000/blogs.
Creating a Fetch Function in App.js
Let's first retrieve the data from our local server. The data will be shown using a template that we’ll generate after successfully retrieving the data and handling any fetch failures.
In our app.js:
import { useState, useEffect } from 'react';
import Blogs from './components/blogs';
import Skeleton from './components/skeleton';
const App = () => {
const [blogs, setBlogs] = useState(null);
const [error, setError] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
setTimeout(() => {
fetch(' http://localhost:8000/blogs')
.then(response => {
if(!response.ok){
throw Error('Sorry, some error occurred while fetching your blogs.');
}
return response.json();
})
.then(data => {
setBlogs(data);
setLoading(false);
setError(false);
})
.catch(err => {
console.log(err.message);
setError(true);
})
}, 4000)
})
return(
<div>
<img className='imagess' src='https://assets.website-files.com/6143afec68f55570f449ef97/6227bdf760fad5f7510a3411_black_logo.svg'></img>
<h1>The Pieces Blog</h1>
{blogs && <Blogs blogs = {blogs} /> }
<div className="container">
{loading && [1,2,3,4,5,6,7].map((n) => <Skeleton key={n}/>)}
</div>
{error && <div className='container'><span className='error'>Error connecting to the server. Connection failed.</span></div>}
</div>
)
}
export default App;
Creating a Blog and Skeleton Components
To continue, we’ll create our blogs.jsx
and skeleton.jsx
components. In the blogs.jsx
, we pass in blogs
as a prop, and then go further to create a template for the different properties of our blog, like blog.title
, blog.description
, etc. While in the skeleton components, we created a function to return a div
that places our blog
, avatar
, title
, author
, etc., in the right location, and in the correct order:
//blogs.js
const Blogs = ({blogs}) => {
return(
<div className="container">
{blogs.map(blog => (
<div className="blog">
<header>
<div className="avatar">
<img src={blog.avatar} alt="black and white photo of smiling man infront of laptop" />
</div>
<div className="author">
<p className="name">{blog.author}</p>
</div>
</header>
<main className="image">
<img src={blog.thumbnail} alt="black screen with code over it" />
</main>
<footer>
<p className="title">{blog.title}</p>
<p className="text">{blog.description}</p>
</footer>
</div>
))}
</div>
);
}
export default Blogs;
//skeleton.js
const Skeleton = () => {
return(
<div className="skeleton-blog">
<header>
<div className="skeleton-avatar">
</div>
<div className="skeleton-author">
</div>
</header>
<main className="skeleton-image">
</main>
<footer className="skeleton-footer">
</footer>
</div>
);
};
export default Skeleton;
Styling Our Skeleton Card
We removed the styling from index.css
so that we could substitute with our very own CSS style. You can check out the complete files and folders here.
This is just a grid layout with a typeface. When the Blog component is imported inside the App component, our blog site should now appear as follows:
Use Cases of Skeleton Loader
- Use to alert viewers that something is loading when several elements are loading simultaneously.
- Use when data loading takes longer than three seconds.
- Use on heavily visited websites.
- Use for a lengthy or background process.
Conclusion
We now understand what skeleton loading is, how it improves user experience by giving the appearance of speedy data loading, and how to put it into practice. The tutorial's source code is available here. Feel free to modify it, style it to be whatever you like, and add code enhancements.
Resources