A skeleton screen is a term coined by Luke Wroblewski for describing a user experience pattern for displaying neutral elements while gradually loading content into a container.
This pattern focuses on improving the perceived performance. When compared against a blank screen or a traditional spinner, skeleton screens are seen as shorter in duration.
Motion and linear-gradient animations are perceived to be quicker than motionless or pulsating loading animations. For images, using their dominant colors with placeholder elements can also be effective.
In this article, you will be presented with several solutions for implementing skeleton screens in your React and React Native applications.
In React, it is possible to achieve a skeleton screen effect with componentDidMount
and a linear gradient.
However, instead of implementing your own solution, you may want to consider some of the more robust community options crafted to encourage scalability: react-content-loader
, react-skeletor
, and react-loading-skeleton
.
react-content-loader
comes loaded with presets for lists, code, and Facebook-styled and Instagram-styled loading cards. It also allows for custom SVG, elements, and color.
Here is an example of react-content-loader
:
import ContentLoader, { Facebook } from 'react-content-loader';
const MyFacebookLoader = () => <Facebook />
const MyLoader = () => (
<ContentLoader>
{/* Pure SVG */}
<rect x="0" y="0" rx="5" ry="5" width="70" height="70" />
<rect x="80" y="17" rx="4" ry="4" width="300" height="13" />
<rect x="80" y="40" rx="3" ry="3" width="250" height="10" />
</ContentLoader>
)
Alternatively, react-placeholder
and SVG-Skeleton
are two other popular out-of-the-box solutions that provide placeholder components and styling.
react-skeletor
allows for full customization by providing higher-order components with direct connections to load conditionals.
Here is an example of react-skeletor
:
import { createSkeletonProvider, createSkeletonElement } from '@trainline/react-skeletor';
const H1 = createSkeletonElement('h1');
const H2 = createSkeletonElement('h2');
const NameCard = ({ firstName, lastName }) => (
<div>
<H1 style={style}>{ firstName }</H1>
<H2 style={style}>{ lastName }</H2>
</div>
)
const UserDetailPage = ({ user }) => (
<div>
...
<NameCard user={user} />
...
</div>
)
export default createSkeletonProvider(
// Dummy data with a similar shape to the component's data.
{
user: {
firstName: '_____',
lastName: '_____'
}
},
// Predicate that returns true if the component is in a loading state.
({ user }) => user === undefined,
// Define the placeholder styling for the children elements.
() => ({
color: 'grey',
backgroundColor: 'grey'
})
)(UserDetailPage)
This blog post goes into further detail on the benefits of using react-skeletor
.
react-loading-skeleton
automatically creates skeleton screens from the styles themselves, eliminating the need to create dedicated skeleton screen components altogether.
Here is an example of react-loading-skeleton
:
import Skeleton from 'react-loading-skeleton';
const Blogpost = () => <div style={{ fontSize: 20, lineHeight: 2 }}>
<h1>{this.props.title || <Skeleton />}</h1>
{this.props.body || <Skeleton count={10} />}
</div>
That concludes using skeleton screens in React.
React Native applications can consider two community options: react-native-svg-animated-linear-gradient
and react-native-shimmer
.
react-native-svg-animated-linear-gradient
can created an animated linear gradient effect.
Here is an example of react-native-svg-animated-linear-gradient
:
import SvgAnimatedLinearGradient from 'react-native-svg-animated-linear-gradient';
// Instagram style.
<SvgAnimatedLinearGradient height={300}>
<Circle cx="30" cy="30" r="30"/>
<Rect x="75" y="13" rx="4" ry="4" width="100" height="13"/>
<Rect x="75" y="37" rx="4" ry="4" width="50" height="8"/>
<Rect x="0" y="70" rx="5" ry="5" width="400" height="200"/>
</SvgAnimatedLinearGradient>
react-native-shimmer
is a React Native implementation of Facebook’s Shimmer implemented in iOS and Android.
Here is an example of react-native-shimmer
:
import Shimmer from 'react-native-shimmer';
<Shimmer>
<Text>Loading...</Text>
</Shimmer>
That concludes using skeleton screens in React Native.
Outside React, the JavaScript community has solved this problem as well. Placeload.js is a popular solution. jquery.skeleton.loader is a jQuery plugin.
And Semantic UI has its own built-in Placeholder
element.
Instead of creating a shimmer effect with gradients, an image’s dominant color can give guidance and context to the user before the content is loaded.
A few resources on extracting the primary colors from an image: color-thief
, node-vibrant
, and color-loader
.
In this article, you were presented with several solutions for implementing skeleton screens in your React and React Native applications.
This presentation by Luke Wroblewski introduces skeleton screens.
These articles go into detail about using skeleton screens: Everything you need to know about skeleton screens and Stop Using Loading Spinner, There’s Something Better.
Serverside Rendering (SSR) is a big part of managing users’ page load experience. Relevant skeleton screens should be included in the “App Shell” and initial page load. Addy Osmani covers how this works with React.
Accessibility should be a consideration as screen-readers and assistive software can become tripped-up and create confusing experiences when it comes to extra page elements like skeleton screens. Ray Roman suggests using ARIA labeling, like aria-disabled={true}
or aria-label="loading"
, to help ignore these elements.
Before implementing skeleton screens, you may wish to consider the counter-arguments in A Bone to Pick with Skeleton Screens.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!