DEV Community

Michael Burrows
Michael Burrows

Posted on

CSS skeleton loading screen animation

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>`
```

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:

```css
.video:empty {
  width: 315px;
  height: 250px; 
  cursor: progress; 
}
```

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:

```css
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;
```

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

```css
background-size: 315px 250px, 315px 180px, 100px 100px, 225px 30px;
```

Next specify the keyframe animation to be used:

```css
animation: loading 1.5s infinite;
```

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

```css
.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;
}
```

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:

```css
@keyframes loading {  
  to {
    background-position: 315px 0, 0 0, 0 190px, 50px 195px;
  }
}
```

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

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iq5nqzvwgssf7qfklezm.gif)

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.

Enter fullscreen mode Exit fullscreen mode

Top comments (8)

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?

Collapse
 
deepu7623 profile image
Deepu Gupta

Thanks for guide us
souqgarden.com