Animate SVG Gradients for Shimmer Skeleton Loaders

A shimmering skeleton loader provides visual feedback to users while content is loading in the background. By utilizing SVG linear gradients and animating their coordinate offsets, you can build lightweight, resolution-independent placeholders that smoothly sweep light across shapes. This guide explains how to define an SVG linear gradient, configure the highlight stops, and animate the gradient across your elements using both native SVG animation (SMIL) and modern CSS techniques.


Understanding the Shimmer Mechanism

A shimmer effect relies on a three-stop <linearGradient>: 1. Base Color: The default placeholder color (e.g., #e0e0e0). 2. Highlight Color: A slightly lighter tone placed in the middle (e.g., #f5f5f5). 3. Base Color: The default placeholder color at the end to create a seamless loop.

To achieve movement, the gradient’s horizontal coordinate attributes (x1 and x2) or translation properties are animated continuously from left to right.


Method 1: Pure SVG with SMIL <animate>

The most self-contained method uses SVG’s native SMIL (Synchronized Multimedia Integration Language) elements. This keeps the animation contained inside the SVG file without relying on external CSS.

<svg viewBox="0 0 400 130" width="100%" height="130" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <!-- Define the gradient with a base width of 100% -->
    <linearGradient id="shimmer" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" stop-color="#e0e0e0" />
      <stop offset="50%" stop-color="#f0f0f0" />
      <stop offset="100%" stop-color="#e0e0e0" />
      
      <!-- Animate x1 and x2 horizontally -->
      <animate 
        attributeName="x1" 
        from="-100%" 
        to="100%" 
        dur="1.5s" 
        repeatCount="indefinite" 
      />
      <animate 
        attributeName="x2" 
        from="0%" 
        to="200%" 
        dur="1.5s" 
        repeatCount="indefinite" 
      />
    </linearGradient>
  </defs>

  <!-- Apply the animated gradient fill to your skeleton shapes -->
  <circle cx="40" cy="40" r="30" fill="url(#shimmer)" />
  <rect x="90" y="20" rx="4" ry="4" width="250" height="16" fill="url(#shimmer)" />
  <rect x="90" y="45" rx="4" ry="4" width="180" height="12" fill="url(#shimmer)" />
  <rect x="10" y="90" rx="4" ry="4" width="330" height="12" fill="url(#shimmer)" />
</svg>

How It Works:


Method 2: Animating via CSS Keyframes

If you prefer controlling the animation globally or managing themes dynamically, you can manipulate the gradient stops or coordinate transforms using CSS.

1. The SVG Markup

<svg class="skeleton-loader" viewBox="0 0 400 100" xmlns="http://www.w3.org/2000/svg">
  <defs>
    <linearGradient id="css-shimmer" x1="0" y1="0" x2="1" y2="0">
      <stop class="stop-base" offset="0%" />
      <stop class="stop-highlight" offset="50%" />
      <stop class="stop-base" offset="100%" />
    </linearGradient>
  </defs>

  <rect x="0" y="0" rx="6" ry="6" width="400" height="100" fill="url(#css-shimmer)" />
</svg>

2. The CSS Animation

.skeleton-loader linearGradient {
  --start: -100%;
  --end: 200%;
}

.stop-base {
  stop-color: #e5e7eb;
}

.stop-highlight {
  stop-color: #f3f4f6;
}

@keyframes shimmer-sweep {
  0% {
    x1: -100%;
    x2: 0%;
  }
  100% {
    x1: 100%;
    x2: 200%;
  }
}

.skeleton-loader linearGradient {
  animation: shimmer-sweep 1.6s infinite linear;
}

Best Practices for Smooth Performance