CSS Animations

While CSS transitions are great for simple "Point A to Point B" changes, CSS animations take things further. They allow you to create complex, multi-step sequences without needing JavaScript. By defining keyframes, you can control an element's appearance at any point during its timeline, creating everything from subtle loading indicators to immersive storytelling effects.

Developer Tip: Use animations for "state-independent" movements (like a constant spinning loader), and use transitions for "state-dependent" changes (like a button changing color when hovered).

Keyframe Animation Syntax

To build an animation, you need two things: a @keyframes rule that defines the stages of the animation, and the animation property applied to the HTML element.

Best Practice: Always give your keyframes descriptive names like @keyframes button-bounce rather than generic ones like @keyframes anim1. It makes your CSS much easier to debug later.

Syntax for Keyframes

@keyframes animationName {
    from {
        /* Starting state (0%) */
        opacity: 0;
    }
    to {
        /* Ending state (100%) */
        opacity: 1;
    }
    
    /* For more control, use percentages to define intermediate steps */
    0% { transform: scale(1); }
    30% { transform: scale(1.1); }
    100% { transform: scale(1); }
}
Watch Out: If you use both from/to and percentages in the same keyframe block, it can become confusing. Stick to percentages if you need more than two steps.

Applying Animations to Elements

Defining the keyframes isn't enough; you have to tell an element to use them. You can do this using the longhand properties for clarity or the shorthand property for efficiency.

Syntax for Animation Property

.element {
    animation-name: slideIn;
    animation-duration: 2s; /* How long the cycle lasts */
    animation-timing-function: ease-in-out; /* The acceleration curve */
    animation-delay: 0.5s; /* Wait time before starting */
    animation-iteration-count: infinite; /* How many times to repeat */
    animation-direction: alternate; /* Go back and forth */
    animation-fill-mode: forwards; /* Stay at the last frame when done */
    animation-play-state: running; /* Can be paused via JS */
}
Common Mistake: Forgetting the animation-duration. By default, it is 0s, meaning the animation will technically run but you’ll never see it.

Animation Properties

1. animation-name

This links your element to the @keyframes identifier you created.

2. animation-duration

Measured in seconds (s) or milliseconds (ms). This defines the total time one single cycle takes to complete.

3. animation-timing-function

Controls the "pacing" of the animation. linear is constant, while ease-in-out feels more natural because it starts slow, speeds up, and slows down at the end. For custom physics, you can use cubic-bezier(n, n, n, n).

4. animation-delay

Useful for staggering animations in a list. For example, you can give each list item a slightly higher delay to create a "waterfall" effect.

5. animation-iteration-count

How many times the animation runs. Use a number (e.g., 3) or the keyword infinite for loops.

6. animation-direction

Determines if the animation plays forward, backward (reverse), or switches back and forth (alternate).

7. animation-fill-mode

One of the most important properties. By default, an element snaps back to its original state after an animation ends. forwards ensures the element stays exactly where the animation finished.

8. animation-play-state

A simple toggle that can be running or paused. This is extremely useful when paired with user interactions like hovering or clicking.

Example of CSS Animation

In this real-world example, we'll create a "sliding box" that moves horizontally. Instead of changing the left property (which is bad for performance), we use transform.

@keyframes slide {
    0% {
        transform: translateX(0);
    }
    100% {
        transform: translateX(100px);
    }
}

.box {
    width: 100px;
    height: 100px;
    background-color: #3498db;
    border-radius: 8px;
    /* Shorthand: name | duration | timing | iteration | direction */
    animation: slide 2s ease-in-out infinite alternate;
}
Developer Tip: Animating transform (scale, rotate, translate) and opacity is much smoother than animating width, height, or top because they are handled by the GPU rather than the main CPU thread.

Animating Multiple Properties

You aren't limited to moving one thing. You can change colors, sizes, and positions all within the same timeline to create a complex effect.

@keyframes status-pulse {
    0% {
        transform: scale(1);
        background-color: #e74c3c; /* Red */
        box-shadow: 0 0 0 0px rgba(231, 76, 60, 0.7);
    }
    70% {
        transform: scale(1.05);
        background-color: #c0392b;
        box-shadow: 0 0 0 10px rgba(231, 76, 60, 0);
    }
    100% {
        transform: scale(1);
        background-color: #e74c3c;
    }
}

.notification-dot {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    animation: status-pulse 2s infinite;
}

Using @keyframes

Keyframes allow you to define intermediate styles at different points. This is perfect for "pulsing" or "shaking" effects where the element needs to return to its original state.

@keyframes pulse {
    0% { transform: scale(1); }
    50% { transform: scale(1.2); }
    100% { transform: scale(1); }
}

.heart-icon {
    display: inline-block;
    animation: pulse 1s ease-in-out infinite;
}
Watch Out: Too many heavy animations running simultaneously (especially those involving shadows or blurs) can drain a user's mobile battery and cause "jank" (stuttering). Use them purposefully.

Controlling Animation States

While CSS handles the visual movement, JavaScript is great for controlling when that movement happens based on logic. A common pattern is pausing a background animation when a user hovers over a specific area.

// Select the element
const element = document.querySelector('.element');

// Pause on mouse enter
element.addEventListener('mouseenter', () => {
    element.style.animationPlayState = 'paused';
});

// Resume on mouse leave
element.addEventListener('mouseleave', () => {
    element.style.animationPlayState = 'running';
});
Best Practice: Instead of manipulating .style directly in JS, toggle a class like .is-paused that has animation-play-state: paused; defined in your CSS. It keeps your concerns separated.

Tips for Using CSS Animations

  1. Performance: Stick to transform and opacity. If you animate properties that trigger "layout" (like margin or height), the browser has to recalculate the entire page layout on every frame, leading to lag.
  2. Browser Compatibility: While modern browsers support CSS animations fully, legacy projects might require -webkit- prefixes for Safari or older versions of Chrome. Always check CanIUse.com if you are targeting older enterprise browsers.
  3. Accessibility: Some users have vestibular disorders and are sensitive to motion. Respect the prefers-reduced-motion media query to disable or simplify animations for those users.