Back

Building Modern Skeleton Screen Loading States

Learn how to create content placeholders with animated shimmer effects for a more engaging and less intrusive loading experience.

HTML

The HTML structure for our skeleton screen loader mimics a typical content card layout, with placeholders for an image and text content. This creates the impression that content is about to appear in a familiar format. We start with a container with the class "skeleton-card" that holds our entire placeholder structure. Inside, we have a "skeleton-img" div that represents a placeholder for an image, followed by a "skeleton-content" section containing placeholder elements for a title and three lines of text.

        <div class="skeleton-card">
          <div class="skeleton-img"></div>
          <div class="skeleton-content">
            <div class="skeleton-title"></div>
            <div class="skeleton-text"></div>
            <div class="skeleton-text"></div>
            <div class="skeleton-text skeleton-text-short"></div>
          </div>
        </div>
      

CSS

First, let's style the card container. We create a clean, white card with subtle shadow and rounded corners to match contemporary UI design practices. The relative positioning and overflow hidden properties are essential for containing the shimmer animation that we'll add later.

        .skeleton-card {
            width: 300px;
            background-color: #FFFFFF;
            border-radius: 8px;
            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
            overflow: hidden;
            position: relative;
        }
      
The shimmer effect is created using a pseudo-element that sweeps across the card. We create a diagonal gradient that's mostly transparent but has a semi-transparent white section in the middle. We initially position this gradient to the left of the card (translateX(-100%)) and then animate it to sweep across and beyond the card (translateX(100%)).

        .skeleton-card::after {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, 
                rgba(255, 255, 255, 0),
                rgba(255, 255, 255, 0.6),
                rgba(255, 255, 255, 0));
            transform: translateX(-100%);
            animation: shimmer 1.5s infinite;
        }
        
        @keyframes shimmer {
            100% {
                transform: translateX(100%);
            }
        }
      
Now, let's style the image placeholder. This tall rectangle at the top of the card mimics a hero image or thumbnail that would typically appear in a content card.

        .skeleton-img {
            height: 150px;
            background-color: #E2E8F0;
        }
      
The content section gets some padding to match typical card layouts, creating space between the placeholder elements.

        .skeleton-content {
            padding: 16px;
        }
      
For the title placeholder, we create a taller rectangle with a light gray background. The rounded corners soften the appearance while it's in the loading state.

        .skeleton-title {
            height: 24px;
            background-color: #E2E8F0;
            border-radius: 4px;
            margin-bottom: 16px;
        }
      
The text placeholders are similar but shorter in height to represent lines of body text. By making the last line shorter (70% width), we create a more natural-looking paragraph structure.

        .skeleton-text {
            height: 12px;
            background-color: #E2E8F0;
            border-radius: 4px;
            margin-bottom: 12px;
        }
        
        .skeleton-text-short {
            width: 70%;
        }
      
Skeleton screens offer numerous advantages over traditional spinners or loaders: - Perceived performance: Users perceive interfaces with skeleton screens to load faster than those with generic loading indicators, even if the actual loading time is identical. - Reduced cognitive load: By previewing the layout that's about to appear, skeleton screens help users mentally prepare for the incoming content. - Lower bounce rates: The immediate visual feedback and layout preview keeps users engaged during loading, reducing the likelihood they'll abandon the page. - Progressive enhancement: As real content loads, it can replace skeleton elements one by one, creating a smooth transition to the fully loaded state. - Brand consistency: Unlike generic spinners, skeleton screens can be styled to match your application's specific layout and design language. This approach to loading states has been adopted by major platforms like LinkedIn, Facebook, and YouTube because it creates a more seamless, less jarring loading experience for users.

Whole code

<div class="skeleton-card">
  <div class="skeleton-img"></div>
  <div class="skeleton-content">
    <div class="skeleton-title"></div>
    <div class="skeleton-text"></div>
    <div class="skeleton-text"></div>
    <div class="skeleton-text skeleton-text-short"></div>
  </div>
</div>

<style>
.skeleton-card {
  width: 300px;
  background-color: #FFFFFF;
  border-radius: 8px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
  overflow: hidden;
  position: relative;
}

.skeleton-card::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, 
    rgba(255, 255, 255, 0),
    rgba(255, 255, 255, 0.6),
    rgba(255, 255, 255, 0));
  transform: translateX(-100%);
  animation: shimmer 1.5s infinite;
}

.skeleton-img {
  height: 150px;
  background-color: #E2E8F0;
}

.skeleton-content {
  padding: 16px;
}

.skeleton-title {
  height: 24px;
  background-color: #E2E8F0;
  border-radius: 4px;
  margin-bottom: 16px;
}

.skeleton-text {
  height: 12px;
  background-color: #E2E8F0;
  border-radius: 4px;
  margin-bottom: 12px;
}

.skeleton-text-short {
  width: 70%;
}

@keyframes shimmer {
  100% {
    transform: translateX(100%);
  }
}
</style>
      
Thank you for reading this article.

Comments

More loaders

Similar

See also