DEV Community

loading...

CSS skeleton loading screen animation

Michael Burrows
Web Developer @ w3collective.com
・2 min read

In this tutorial we’ll be using CSS to create an animated skeleton loading screen. Skeleton loading screens provide an approximate representation of a site layout while a page is loading data. This lets users know that the content is loading and unlike a full page loading screen individual elements of the page can be loading in gradually using this technique.

Today we’ll create a skeleton screen for a video card component that’ll look like this:

Alt Text

For the HTML we only require is single empty <div> element:

<div class="video"></div>`
Enter fullscreen mode Exit fullscreen mode

Now we can start with the CSS. We’ll use the :empty pseudo-class that will only display the skeleton when the video <div> is empty (including whitespace) and disappear once content has been injected. Developers often use a toggle class to achieve the same effect but this solution is much simpler:

.video:empty {
  width: 315px;
  height: 250px; 
  cursor: progress; 
}
Enter fullscreen mode Exit fullscreen mode

The video component contains 4 elements, a semi transparent overlay that we’ll animating to give the illusion of data being fetched, then skeleton representations of a thumbnail, avatar and title text. These 4 elements are created using background CSS gradients. For the skeleton elements we achieve a solid color by using the same color value for both gradient endpoints:

background: 
  linear-gradient(0.25turn, transparent, #fff, transparent),
  linear-gradient(#eee, #eee),
  radial-gradient(38px circle at 19px 19px, #eee 50%, transparent 51%),
  linear-gradient(#eee, #eee);
background-repeat: no-repeat;
Enter fullscreen mode Exit fullscreen mode

Now we need to define the size for each of these elements:

background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px;
Enter fullscreen mode Exit fullscreen mode

Next specify the keyframe animation to be used:

animation: loading 1.5s infinite;
Enter fullscreen mode Exit fullscreen mode

Here’s what the complete .video class looks like:

.video:empty {
  width: 315px;
  height: 250px; 
  cursor: progress; 
  background: 
    linear-gradient(0.25turn, transparent, #fff, transparent),
    linear-gradient(#eee, #eee),
    radial-gradient(38px circle at 19px 19px, #eee 50%, transparent 51%),
    linear-gradient(#eee, #eee);  
  background-repeat: no-repeat;
  background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px; 
  background-position: -315px 0, 0 0, 0px 190px, 50px 195px; 
  animation: loading 1.5s infinite;
}
Enter fullscreen mode Exit fullscreen mode

Final thing to do is add the @keyframes animation to the first gradient by shifting the x-axis of the background position to the right hand edge of the parent element. You could also experiment with animating the opacity here for extra visual appeal:

@keyframes loading {  
  to {
    background-position: 315px 0, 0 0, 0 190px, 50px 195px;
  }
}
Enter fullscreen mode Exit fullscreen mode

You can now test this code out in a browser, here’s what it should look like:

Alt Text

Hopefully you found this tutorial useful and it serves as a good starting point for building all types of different skeleton loading screens. If you are having trouble figuring out the whole background gradient thing try starting with a single skeleton element before adding additional elements.

Discussion (7)

Collapse
ashleyjsheridan profile image
Ashley Sheridan

Just wanted to mention that while subtle animations like this are a useful UX tool, we also have to be wary of animation use where a user has specifically opted out of them, e.g. for accessibility reasons (people with vestibular problems often disable animations). You can put the animation part of this skeleton into a media query:

@media screen and (prefers-reduced-motion: no-preference) { }
Enter fullscreen mode Exit fullscreen mode

Another aspect of accessibility would be for screen reader users, as they might not necessarily be able to see what's happening visually on the screen. For those people, you can add some additional text (visually hidden) like this:

<div class="video"><span class="visually-hidden">Loading</span></div>
Enter fullscreen mode Exit fullscreen mode

Then you can hide that text visually but make it available to screen readers with CSS like this:

.visually-hidden {
    clip: rect(1px, 1px, 1px, 1px);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: auto;
}
Enter fullscreen mode Exit fullscreen mode
Collapse
nikbabchenko profile image
nikbabchenko

Nice article.
Btw, there are great packages for skeleton:
WebComponent (could be used in any app) - npmjs.com/package/skeleton-webcomp...
Angular - github.com/willmendesneto/ngx-skel...
React - npmjs.com/package/react-loading-sk...

Collapse
lawaldare profile image
Dare Lawal

Thanks man!

Collapse
afif profile image
Temani Afif

I would use mask like this: jsfiddle.net/s85o9ag6/ to have transparency as well.

Collapse
timhuang profile image
Timothy Huang

Amazing effect on css, thanks for sharing.

Collapse
adithyakam profile image
adithyakam

Man great post ,really helpfull

Collapse
torskint profile image
Tor Skint

What about support for older browsers?