Animated Loading Skeletons with Tailwind CSS

Jul 18, 2022

Animated Loading Skeletons with Tailwind CSS

Skeleton

  • Use Tailwind's range of utility classes to create a skeleton that roughly resembles the content you're about to load.
<div className="space-y-5 rounded-2xl bg-white/5 p-4">
  <div className="h-24 rounded-lg bg-rose-100/10"></div>
  <div className="space-y-3">
    <div className="h-3 w-3/5 rounded-lg bg-rose-100/10"></div>
    <div className="h-3 w-4/5 rounded-lg bg-rose-100/20"></div>
    <div className="h-3 w-2/5 rounded-lg bg-rose-100/20"></div>
  </div>
</div>

Gradient overlay

  • Use Tailwind's gradient color stops to create a gradient that fades from transparent to white and back to transparent.
<div
  className="
    [...]
    bg-gradient-to-r from-transparent via-rose-100/10 to-transparent"
></div>

Animation

  • Define a CSS keyframe animation that translates elements 100% to the right in the extend keyframes object of tailwind.config.js.
  • Use Tailwind's arbitrary values to apply the keyframe animation to the overlay element.
{
  "keyframes": {
    "shimmer": {
      "100%": {
        "transform": "translateX(100%)",
      },
    },
  }
},
<div className="[...] -translate-x-full animate-[shimmer_2s_infinite]"></div>

Combine the skeleton and overlay animation

  • Add the overlay to a pseudo-element of the skeleton wrapper using Tailwind's before: modifier.
<div
  className="
    [...]
    relative 
    before:absolute before:inset-0
    before:-translate-x-full
    before:animate-[shimmer_2s_infinite]
    before:bg-gradient-to-r
    before:from-transparent before:via-rose-100/10 before:to-transparent"
>
  [...]
</div>

Finishing touches

  • Hide the overlay while it's positioned outside the skeleton.
  • Add a shadow to the skeleton.
  • Add a subtle border to the top of the overlay to simulate reflecting light.
  • You can fix Safari overflowing the animation on rounded corners with isolate.
<div
  className="
    [...]
    isolate
    overflow-hidden
    shadow-xl shadow-black/5
    before:border-t before:border-rose-100/10"
>
  [...]
</div>