Skillversitas

Animation Examples

CSS keyframe animations let you create complex animations with full control. From a simple loading spinner to a dramatic entrance animation, keyframes provide a declarative way to bring an interface to life.

CSS animations are more performant than JavaScript because they can be GPU-accelerated. But use them wisely — too many animations can disturb the UX and drain a mobile device's battery.

The examples below cover animations that are commonly used in everyday web development.

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
<style>
  body {
    font-family: 'Segoe UI', Arial, sans-serif;
    padding: 40px 20px;
    background: #1a1a2e;
    color: white;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 40px;
  }

  .demo-card {
    background: rgba(255,255,255,0.08);
    padding: 30px;
    border-radius: 16px;
    width: 300px;
    text-align: center;
  }

  .demo-card h3 {
    margin-top: 0;
    font-size: 1em;
    color: #aaa;
    margin-bottom: 20px;
  }

  /* === 1. Loading Spinner === */
  .spinner {
    width: 50px;
    height: 50px;
    border: 4px solid rgba(255,255,255,0.1);
    border-top-color: #667eea;
    border-radius: 50%;
    margin: 0 auto;
    animation: spin 0.8s linear infinite;
  }

  @keyframes spin {
    to { transform: rotate(360deg); }
  }

  /* === 2. Dual Ring Spinner === */
  .dual-ring {
    width: 50px;
    height: 50px;
    border: 4px solid transparent;
    border-top-color: #f093fb;
    border-bottom-color: #f093fb;
    border-radius: 50%;
    margin: 0 auto;
    animation: spin 1s linear infinite;
    position: relative;
  }

  .dual-ring::before {
    content: '';
    position: absolute;
    inset: 6px;
    border: 4px solid transparent;
    border-left-color: #f5576c;
    border-right-color: #f5576c;
    border-radius: 50%;
    animation: spin 0.6s linear infinite reverse;
  }

  /* === 3. Typing Cursor === */
  .typing-container {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 40px;
  }

  .typing-text {
    font-size: 1.2em;
    font-family: monospace;
    border-right: 2px solid white;
    padding-right: 5px;
    animation: blink-caret 0.7s step-end infinite;
    white-space: nowrap;
    overflow: hidden;
    animation: typing 2s steps(20) forwards, blink-caret 0.7s step-end infinite;
  }

  @keyframes typing {
    from { width: 0; }
    to { width: 100%; }
  }

  @keyframes blink-caret {
    50% { border-color: transparent; }
  }

  /* === 4. Bounce === */
  .bounce {
    width: 60px;
    height: 60px;
    background: linear-gradient(135deg, #667eea, #764ba2);
    border-radius: 12px;
    margin: 0 auto;
    animation: bounce 1s ease infinite;
  }

  @keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-20px); }
  }

  /* === 5. Heartbeat Pulse === */
  .heartbeat {
    font-size: 3em;
    animation: heartbeat 1.2s ease-in-out infinite;
    display: inline-block;
  }

  @keyframes heartbeat {
    0%, 100% { transform: scale(1); }
    14% { transform: scale(1.3); }
    28% { transform: scale(1); }
    42% { transform: scale(1.3); }
    70% { transform: scale(1); }
  }

  /* === 6. Wave === */
  .wave-container {
    display: flex;
    gap: 5px;
    justify-content: center;
    align-items: flex-end;
    height: 50px;
  }

  .wave-bar {
    width: 8px;
    height: 20px;
    background: #4ecdc4;
    border-radius: 4px;
    animation: wave 1.2s ease-in-out infinite;
  }

  .wave-bar:nth-child(1) { animation-delay: 0s; }
  .wave-bar:nth-child(2) { animation-delay: 0.1s; }
  .wave-bar:nth-child(3) { animation-delay: 0.2s; }
  .wave-bar:nth-child(4) { animation-delay: 0.3s; }
  .wave-bar:nth-child(5) { animation-delay: 0.4s; }

  @keyframes wave {
    0%, 100% { height: 20px; }
    50% { height: 45px; }
  }

  /* === 7. Fade In === */
  .fade-in {
    animation: fadeIn 1.5s ease forwards;
  }

  @keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
  }

  /* === 8. Slide In === */
  .slide-in-left {
    animation: slideInLeft 0.6s ease forwards;
  }

  @keyframes slideInLeft {
    from { opacity: 0; transform: translateX(-50px); }
    to { opacity: 1; transform: translateX(0); }
  }

  /* === 9. Pulse Ring === */
  .pulse-ring {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: #667eea;
    margin: 0 auto;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
  }

  .pulse-ring::before,
  .pulse-ring::after {
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 2px solid #667eea;
    animation: pulseRing 2s ease-out infinite;
  }

  .pulse-ring::after {
    animation-delay: 0.5s;
  }

  @keyframes pulseRing {
    0% { transform: scale(1); opacity: 0.8; }
    100% { transform: scale(2); opacity: 0; }
  }

  /* === 10. Gradient Shift === */
  .gradient-shift {
    width: 200px;
    height: 60px;
    border-radius: 30px;
    background: linear-gradient(90deg, #667eea, #764ba2, #f093fb, #f5576c, #667eea);
    background-size: 300% 100%;
    animation: gradientShift 3s ease infinite;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    color: white;
  }

  @keyframes gradientShift {
    0% { background-position: 0% 50%; }
    50% { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
  }

  /* === 11. Flip Card === */
  .flip-container {
    perspective: 1000px;
    width: 120px;
    height: 80px;
    margin: 0 auto;
  }

  .flip-card {
    width: 100%;
    height: 100%;
    position: relative;
    animation: flipCard 2s ease-in-out infinite;
    transform-style: preserve-3d;
  }

  .flip-card .front,
  .flip-card .back {
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    backface-visibility: hidden;
    font-weight: bold;
  }

  .flip-card .front {
    background: #667eea;
    color: white;
  }

  .flip-card .back {
    background: #f5576c;
    color: white;
    transform: rotateY(180deg);
  }

  @keyframes flipCard {
    0%, 100% { transform: rotateY(0deg); }
    50% { transform: rotateY(180deg); }
  }

  /* === 12. Shake === */
  .shake {
    animation: shake 0.5s ease;
    display: inline-block;
    font-size: 2em;
  }

  @keyframes shake {
    0%, 100% { transform: translateX(0); }
    20% { transform: translateX(-10px); }
    40% { transform: translateX(10px); }
    60% { transform: translateX(-5px); }
    80% { transform: translateX(5px); }
  }
</style>
</head>
<body>
  <div class="demo-card">
    <h3>Loading Spinner</h3>
    <div class="spinner"></div>
  </div>

  <div class="demo-card">
    <h3>Dual Ring Spinner</h3>
    <div class="dual-ring"></div>
  </div>

  <div class="demo-card">
    <h3>Typing Cursor</h3>
    <div class="typing-container">
      <span class="typing-text">Hello, welcome!</span>
    </div>
  </div>

  <div class="demo-card">
    <h3>Bounce</h3>
    <div class="bounce"></div>
  </div>

  <div class="demo-card">
    <h3>Heartbeat</h3>
    <div class="heartbeat">❤️</div>
  </div>

  <div class="demo-card">
    <h3>Wave</h3>
    <div class="wave-container">
      <div class="wave-bar"></div>
      <div class="wave-bar"></div>
      <div class="wave-bar"></div>
      <div class="wave-bar"></div>
      <div class="wave-bar"></div>
    </div>
  </div>

  <div class="demo-card">
    <h3>Gradient Shift</h3>
    <div class="gradient-shift">Loading...</div>
  </div>

  <div class="demo-card">
    <h3>Flip Card</h3>
    <div class="flip-container">
      <div class="flip-card">
        <div class="front">FRONT</div>
        <div class="back">BACK</div>
      </div>
    </div>
  </div>

  <div class="demo-card">
    <h3>Pulse Ring</h3>
    <div class="pulse-ring"></div>
  </div>
</body>
</html>

Code Explanation

Loading Spinner: A border with only one colored side, rotating 360 degrees. border-radius: 50% creates the circle, and animation: spin 0.8s linear infinite rotates it continuously.

Typing Cursor: Uses overflow: hidden and an animated width from 0 to 100%. The steps() function creates the character-by-character typing effect. The border-right blinks as the cursor.

Bounce: The object moves up and down with translateY. The ease timing function gives it a natural feel.

Heartbeat: The scale changes in a specific pattern (small-big-small-big-small), mimicking a heartbeat. The delay between beats makes it feel natural.

Wave: Multiple bars with different animation-delay values create a wave effect. Each bar moves up and down with a time offset.

Gradient Shift: background-size: 300% gives the gradient room to move. background-position is animated to create the shifting effect.

Flip Card: transform-style: preserve-3d and backface-visibility: hidden enable the 3D flip effect. The two sides of the card are positioned differently with rotateY(180deg).

Pulse Ring: Pseudo-elements with scale from 1 to 2 and opacity from 0.8 to 0 create a spreading wave effect.

Everyday Use Cases

Loading states: A spinner while waiting for data to load from the server.

Empty states: A bounce or pulse animation on an empty-state illustration.

Call to action: A gradient shift on a CTA button to draw attention.

Notifications: A shake animation on a notification icon when a new message arrives.

Social media: A heartbeat on a like/love button.

Conclusion

Keyframe animations open up a wide range of visual possibilities. Common patterns: transform (translate, rotate, scale, skew), opacity (fade), and color/gradients. Use animation-delay for sequencing. Timing functions (ease, linear, ease-in-out, cubic-bezier) control the feel of the animation. Consider performance — avoid animating properties that trigger layout recalculation such as width, height, top, left.