References

Beginner-friendly references for web development, with live, editable examples.

The CSS @keyframes at-rule

At-rule CSS All modern browsers Updated
Quick answer

The CSS @keyframes at-rule defines the steps of an animation — what styles apply at each point, using from/to or percentages from 0% to 100%. You give it a name, then play it with the animation property. Together they create spinners, fades, slides and more, with no JavaScript.

Overview

@keyframes is where a CSS animation is choreographed. You give the animation a name and list its waypoints — the styles the element should have at each moment in the cycle. The browser fills in the smooth transitions between them.

Simple animations use from and to (the same as 0% and 100%); multi-step ones use percentages, like 0%, 50%, 100%, to define stops along the way. Once defined, the keyframes do nothing on their own — you attach them to an element with the animation property, which sets the name, duration, easing and repeat.

As with all motion in CSS, animate transform and opacity for the smoothest results — the browser can hand those to the GPU. Name your keyframes for what they do (slide-in, pulse) so the stylesheet stays readable.

Syntax

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

.item {
  animation: slide-in 0.4s ease-out;
}

Example

Live example
<style>
  @keyframes slidein { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
  @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.18); } }
  .row { display: flex; gap: 22px; align-items: center; justify-content: center; padding: 22px; font: 600 13px system-ui, sans-serif; }
  .slide { animation: slidein 1.3s ease-out infinite alternate; background: #1c7ce9; color: #fff; padding: 12px 16px; border-radius: 8px; }
  .dot { width: 30px; height: 30px; border-radius: 50%; background: #6d28d9; animation: pulse 1.3s ease-in-out infinite; }
</style>
<div class="row"><div class="slide">slide</div><div class="dot"></div></div>

Best practices

  • Animate transform and opacity inside keyframes for smooth, GPU-friendly motion.
  • Use from/to for simple two-step animations and percentages for multi-step ones.
  • Name keyframes descriptively so the animation declarations read clearly.
  • Gate non-essential animation behind @media (prefers-reduced-motion: no-preference).

Accessibility

Keyframe animations are motion, so they fall under the same care as any animation: respect prefers-reduced-motion. Wrap decorative or looping animations in @media (prefers-reduced-motion: no-preference) so people who are sensitive to movement get a still interface. Avoid anything that flashes more than three times a second, and make sure long or infinite animations can be paused.

Frequently asked questions

How do I create an animation with @keyframes?
Define the steps in @keyframes name { … }, then attach it with the animation property, e.g. animation: name 1s ease infinite.
What is the difference between from/to and percentages?
from and to are shorthand for 0% and 100% — fine for two-step animations. Percentages let you define multiple stops in between for multi-step motion.
How do I make a keyframe animation loop?
Set the iteration count on the animation property to infinite, e.g. animation: pulse 2s ease-in-out infinite.
What is the difference between @keyframes and transition?
A transition animates between two states when a value changes. @keyframes with animation can run on its own, loop, and define many in-between steps.