CSS Skeleton Loading 💀
Tags: html, css, javascript
Published: 2020-09-11 16:08:56

Skeleton loading is a strategy/technique for improving user experience. In this post I want to share an example of how I would approach it without any UI libraries or fancy components.

Basically, skeleton loading is aimed at components or content areas that are being fetched from a backend or an API. We can use a loader for the entire page or even individual components, but this approach sometimes results in a flaky user experience. However, when applying skeleton loading we ensure that the basic structure of the page and its components are visible. Once our content is ready, we can remove the skeleton loaders and display the content.

Here is my skeleton loading example on codepen.io:

https://codepen.io/yossi_abramov/pen/jOqxOQp

### A quick breakdown

For this example, I created a user card component that contains an avatar, name, email and contact button. The user card content is hard-coded for the sake of simplicity. In a real app or website you would probably fetch data and update the  `DOM`  with it.

```xml
<div class="user-card skeleton">
    <div class="user-cover">
      <img class="user-avatar" src="
        https://yossiabramov.com/images/avatar.jpeg" alt="user profile image" />
    </div>
    <div class="user-details">
      <div class="user-name hide-text">Yossi Abramov</div>
      <div class="user-email hide-text">josephabramov90@gmail.com</div>
    </div>
    <button class="contact-user hide-text">CONTACT</button>
</div>
```

Notice that the  `.user-card`  element has a  `.skeleton`  class and every element that contains text has a  `.hide-text`  class.

Now, this example is a bit CSS heavy so let’s go over the most important lines:

```css
/* Skeleton */

/* Static Skeleton */

.user-card.skeleton .user-cover {
  background: #e2e2e2;
}

.user-card.skeleton .user-cover .user-avatar {
  display: none;
}

.user-card.skeleton .user-cover::after {
  content: "";
  position: absolute;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  left: 0;
  right: 0;
  margin: auto;
  bottom: -25px;
  border: 1px solid #fff;
  z-index: 10;
  background: #e2e2e2;
}

/* Animated Skeleton */

.user-card.skeleton .hide-text {
  background: #e2e2e2;
  color: transparent;
  position: relative;
  overflow: hidden;
}

.user-card.skeleton .hide-text::before {
  content: "";
  position: absolute;
  left: 0%;
  top: 0;
  height: 100%;
  width: 50px;
  background: linear-gradient(to right, #e2e2e2 25%, #d5d5d5 50%, #e2e2e2 100%);
  animation-name: gradient-animation;
  animation-duration: 2s;
  animation-iteration-count: infinite;
  filter: blur(5px);
}

@keyframes gradient-animation {
  from {
    left: 0%;
  }
  to {
    left: 100%;
  }
}
```

Basically, I have two states of skeleton loading: static and animated. The  `.user-cover`  and  `.user-avatar`  elements have a static skeleton – without any CSS transition or keyframe animation applied to them while all elements with the  `.hide-text`  class have a keyframe animation. The  `gradient-animation`  animation is applied to a  `::before`  element that is positioned  `absolute`  to it’s  `relative`  `.hide-text`  father. The animation is very simple but effective.

The JavaScript for this example only simulates a somewhat slow fetching of data. Once our data is fetched, we can remove our skeleton loaders.

```javascript
const $el = document.querySelector(".user-card");

// Loading finished
setTimeout(() => {
  $el.classList.remove("skeleton");
  $el
    .querySelectorAll(".hide-text")
    .forEach((el) => el.classList.remove("hide-text"));
}, 3000);
```

Hope you find this approach to skeleton loading simple and clear 🙏 .

✍ For more posts:
[https://yossiabramov.com/](https://yossiabramov.com/)