DEV Community

loading...
Cover image for How to Build a Skeleton Layout in React

How to Build a Skeleton Layout in React

lukekyl profile image Kyle Luke Updated on ・3 min read

The use of a Skeleton Layout for asynchronous content is becoming more and more popular across mobile and web apps alike. Google, Facebook, LinkedIn, Youtube and many more use a skeleton layout to display what the content and layout might look like, before it loads. Using one in your own project is a nice styling effect for your users, and also might just improve the SEO of your project in the near future by reducing "cumulative layout shift". This post shows you how easy it is to add a skeleton layout that updates after asynchronous content is loaded.

LinkedIn Skeleton Layout Example from: https://uxdesign.cc/what-you-should-know-about-skeleton-screens-a820c45a571a

isLoaded State

React allows for us to set state from isLoaded: false to isLoaded: true when an asynchronous function has completed. This will be the basis for which set of content we will display. We will create two CSS classes for our content based on the isLoaded state: .loading and .loaded. We will then do an if statement that will return the JSX for the .loaded content, IF isLoaded = true. IF isLoaded = false, the app will return the JSX for the .loading content, which will be our skeleton layout.

// JSX
class App extends React.Component {
  constructor(props){
    super(props);

    this.state = {
      isLoaded: false,
      asyncData: []
    }
  };

render(){

    asyncFunction = () => {
        // Async function fetches asyncData, and upon fetch updates state from `isLoaded:false` to `isLoaded:true`
    }

    if(this.state.isLoaded===true){
        // If state.isLoaded=true, component will render complete layout and async content
          return(
            <>
              <LayoutContent className="loaded" />
            </>
          );
        } 

    return(
      // While state.isLoaded=false, component will only render skeleton layout
        <>
            <LayoutContent className="loading" />
        </>
    );
};
};
Enter fullscreen mode Exit fullscreen mode

CSS

The CSS we need to style will include our two classes: .loading and .loaded. This gives you a little freedom for how you would like your skeleton layout to look, but I chose an animated approach from StackFindOver for the styling in the CodePen example below.

// Skeleton Layout styles and animation
.loading {
    position: relative;
    background: #cccccc;
}
.loading:after {
    content: "";
    display: block;
    position: absolute;
    top:0;
    width: 100%;
    height: 100%;
    transform: translateX(-100px);
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
    animation: loading 0.8s infinite;
}
@keyframes loading {
    100% {
        transform: translateX(100%);
    }
}

// Loaded styling
.loaded {
    // Styles
}
Enter fullscreen mode Exit fullscreen mode

Some additional things to note when it comes to CSS styling:

  • Width and Height of components should be defined to reduce content jumping
  • Consider using CSS Flexbox for responsive components with max-width/height defined
  • If component sizes vary based on content consider adding an "overflow-y: scroll" property

Example Application

Feel free to steal some of the code from this CodePen example, but note you will likely need to adjust some of the styling to fit your own application.

Conclusion

Skeleton layouts not only give your application a fun and useful loading screen as asynchronous content loads, but also might just improve your application's SEO and user experience. Hopefully this blog post and the example gives you some ideas on how to apply a skeleton layout in your own project!

Have you used a Skeleton Layout in your project?
Comment if you have used a similar method, or have suggestions for improvements!

Discussion (12)

pic
Editor guide
Collapse
degesis profile image
PovilasB

Great article! One tip tho - ditch the loading boolean state. There is more than loading/done states. Best approach is to have idle/loading/success/error states. More management is required but, it saves users from waiting despite API call has failed.

This article by Kent is great explanation why:
kentcdodds.com/blog/stop-using-isl...

Collapse
xavierbrinonecs profile image
Xavier Brinon

ahah, I was about to post this, well played.

Collapse
nikitaneganov profile image
NikitaNeganov

Actually, his (Kent's) initial structure is not that bad, in his specific case all he needed to do is a) clear position on error or b) move error check higher that position check, i.e. ensuring error's priority

Collapse
lukekyl profile image
Kyle Luke Author

Great tip, I will look into this article! Thanks a ton!!!

Collapse
james_baxter_9deedb25c4e6 profile image
James Baxter

I wish people would stop quoting Kent C Dodds.

Collapse
iridiumcodes profile image
Iris Diakoumi

Why is that?

Collapse
dennismaina profile image
Dennis Maina

Great write up. I always wondered how these guys did it but this article really gave me a head start 😊

Collapse
james_baxter_9deedb25c4e6 profile image
James Baxter

Awesome sauce! You should be using functional components. Class based components are no longer recommended.

Collapse
lukekyl profile image
Kyle Luke Author

Thanks James, I was thinking that when building the example but wanted to keep this code tutorial accessible to users that may have not made that switch. I might consider transitioning the codepen in the near future.

Collapse
techyniel profile image
Techyniel

Great

Collapse
anthonybrown profile image
Tony Brown

Nice 👍