CSS @keyframes: Creating Animations

Define the blueprint for your CSS animations, from simple fades to complex, multi-step sequences using the powerful `@keyframes` at-rule.

Lesson ProgressStep 1 of 9
0 EXP

Hello! Let's build a CSS animation from scratch. We'll use the @keyframes rule to define the animation's steps.

/* Welcome to the CSS Animation Simulator */

The @keyframes Rule

The heart of any CSS animation is the @keyframes at-rule. This is where you define the "blueprint" for your animation. You give your animation a unique name that you will use to apply it to an element later.

@keyframes my-animation-name {
  /* Keyframe steps (e.g., 0%, 50%, 100%) go here */
}

The name (e.g., `my-animation-name`) can be anything you want, but it's best to choose a descriptive name.

System Check

What is the primary purpose of the @keyframes rule?

Advanced Holo-Simulations

0 EXP

Apply your knowledge and earn achievements.


Achievements

🏆
Keyframe Creator

Successfully define your first @keyframes animation rule.

🏗️
Timeline Architect

Use percentages (e.g., 0%, 50%, 100%) to build a multi-step animation.

✍️
Animation Master

Apply a complex animation using the shorthand property.

Mission: Build and Apply an Animation

Create a `@keyframes` animation named `grow` that scales an element from `scale(1)` to `scale(1.5)`. Then, apply this animation to the `.my-box` class with a duration of 3 seconds.

A.D.A. Feedback:

> System integrity looks stable. Code is valid.

Challenge: Order the Animation Rule

The syntax of a `@keyframes` rule is precise. Drag the lines of code into the correct order.

  from { opacity: 0; }
}
@keyframes fadeIn {
  to { opacity: 1; }

Challenge: Complete the Shorthand

Fill in the missing parts to apply an animation named `pulse` that runs for `2s` and loops `infinite`ly, using the shorthand property.

.my-element {:2s; }

Consult A.D.A.

Community Holo-Net

Choreographing the Web: A Deep Dive into CSS @keyframes

While CSS Transitions are perfect for simple state changes (like a hover effect), **`@keyframes`** are the engine for creating complex, multi-step animations. They give you the power to act as a director, dictating exactly what an element should be doing at any point during its timeline. This article dives deep into the `@keyframes` rule and its powerful companion, the `animation` property.

Section 1: The Core Syntax of @keyframes

The `@keyframes` at-rule is a block of code that defines the animation. You give it a unique name, and then define "keyframes" (or steps) inside it using percentages, or the keywords `from` and `to`.

Using `from` and `to`

For a simple, two-step animation, `from` (the starting state, or `0%`) and `to` (the ending state, or `100%`) are the most straightforward.

/* This animation will fade an element in */
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

Using Percentages

For more than two steps, percentages are required. You can add as many as you like, from `0%` to `100%`, to create complex sequences.

/* This animation creates a 'pulse' effect */
@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

You can even group selectors. The `pulse` animation above is more efficiently written by grouping the `0%` and `100%` states, since they share the same styles: `0%, 100% transform: scale(1);`.

Section 2: Applying Your Animation

Defining a `@keyframes` rule does nothing on its own. You must apply it to an element using the `animation` properties. While you can use the `animation` shorthand, it's crucial to understand the long-form properties it controls.

  • `animation-name`: Specifies the name of the `@keyframes` rule to apply (e.g., `fadeIn`).
  • `animation-duration`: Sets the length of time the animation takes to complete one cycle (e.g., `2s` or `500ms`). **This is required.**
  • `animation-timing-function`: Controls the speed curve of the animation. Common values are `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`, `steps()`, and the advanced `cubic-bezier()` function.
  • `animation-delay`: Sets a delay before the animation begins (e.g., `1s`).
  • `animation-iteration-count`: Defines how many times the animation should run. Use a number (e.g., `3`) or the keyword `infinite` to loop it forever.
  • `animation-direction`: Sets whether the animation should play forwards, backwards, or alternate. Values: `normal`, `reverse`, `alternate`, `alternate-reverse`.
  • `animation-fill-mode`: This is a critical property. It defines what styles apply to the element *before* the animation starts and *after* it ends.
    • `none` (default): Element is styled as-is, then animates, then reverts to its original style.
    • `forwards`: After the animation finishes, the element will retain the styles from the *last keyframe* (`100%`).
    • `backwards`: Before the animation starts (during a delay), the element will adopt the styles from the *first keyframe* (`0%`).
    • `both`: Applies the rules for both `forwards` and `backwards`.
  • `animation-play-state`: Allows you to pause (`paused`) and resume (`running`) an animation, often controlled with JavaScript.

The `animation` Shorthand

It's much more common to use the `animation` shorthand. The order is important, though modern browsers are quite good at parsing it. A common pattern is:

/* [name] [duration] [timing-function] [delay] [iteration-count] [direction] [fill-mode] */
.my-element {
  animation: pulse 2s ease-in-out 1s infinite alternate forwards;
}

Section 3: Performance and Accessibility

Hardware Acceleration for Smooth Animations

Not all properties are cheap to animate. Animating properties like `width`, `height`, `left`, `top`, or `margin` forces the browser to "re-layout" the page, which is slow and can cause janky, stuttering animations.

For best performance, stick to animating properties that the browser's GPU can handle:

  • `transform` (e.g., `translateX()`, `scale()`, `rotate()`)
  • `opacity`

❌ Bad (Slow)

@keyframes slide {
  from { left: 0; }
  to { left: 100px; }
}

Animates `left`, causing layout reflows.

✔️ Good (Fast)

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

Animates `transform`, which is GPU-accelerated.

Accessibility: `prefers-reduced-motion`

Some users experience motion sickness or vestibular disorders from large movements. It is a crucial accessibility best practice to respect their preference by disabling or reducing animations inside a `prefers-reduced-motion` media query.

/* Standard animation */
.my-element {
  animation: slide-in 1s ease-out;
}

/* Disable animations for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
  .my-element {
    animation: none;
  }
}
Key Takeaway: `@keyframes` are the most powerful tool in your CSS animation arsenal. By combining them with the `animation` properties, you can create anything from subtle pulses to complex, cinematic sequences. Always prioritize `transform` and `opacity` for performance, and respect `prefers-reduced-motion` for accessibility.

CSS Animation Glossary

`@keyframes`
The at-rule used to define the steps of a CSS animation. It contains a set of keyframe selectors (like `0%`, `50%`, `100%`) that define the styles at each stage of the animation's timeline.
`animation`
The shorthand property for setting all the long-form animation properties in a single declaration.
`animation-name`
Specifies the name of the `@keyframes` rule that should be applied to the element.
`animation-duration`
Defines the length of time, in seconds (`s`) or milliseconds (`ms`), that one cycle of the animation should take to complete.
`animation-timing-function`
Controls the speed curve, or "easing," of the animation. It defines how the animation progresses between keyframes (e.g., `ease-in`, `linear`, `cubic-bezier(0.25, 0.1, 0.25, 1.0)`).
`steps()`
A special timing function that divides the animation into a set number of steps, creating a "stepped" or "ticker" effect rather than a smooth transition.
`animation-delay`
Specifies a delay to wait before the animation starts playing.
`animation-iteration-count`
Sets the number of times the animation cycle should be played. Can be a number (e.g., `3`) or the keyword `infinite`.
`animation-direction`
Defines the direction of play. `normal` (default), `reverse` (plays backwards), `alternate` (plays forwards, then backwards), `alternate-reverse` (plays backwards, then forwards).
`animation-fill-mode`
A crucial property that dictates an element's styles outside of the animation's execution time (i.e., before it starts or after it ends). `forwards` is commonly used to make an animation "stick" at its final state.
`animation-play-state`
Allows for pausing (`paused`) and resuming (`running`) an animation, typically via JavaScript.
Hardware Acceleration
The browser offloads animation calculations to the GPU (Graphics Processing Unit) for smoother performance. This is generally triggered when animating `transform` and `opacity`.
`prefers-reduced-motion`
A CSS media query used to detect if the user has requested that the system minimize the amount of non-essential motion. Used for accessibility.

About the Author

Author's Avatar

TodoTutorial Team

Passionate developers and educators making programming accessible to everyone.

This article was written and reviewed by our team of web development experts, who have years of experience teaching CSS and building robust, animated, and accessible web applications.

Verification and Updates

Last reviewed: November 2025.

We strive to keep our content accurate and up-to-date. This tutorial is based on the latest CSS Animations Level 1 specifications and is periodically reviewed to reflect industry best practices.

External Resources

Found an error or have a suggestion? Contact us!