@keyframes

/* Define the animation */
@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* With multiple stops */
@keyframes pulse {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.05); }
  100% { transform: scale(1); }
}

/* Easing per step */
@keyframes bounce {
  0%, 100% { transform: translateY(0); animation-timing-function: ease-in; }
  50%       { transform: translateY(-20px); animation-timing-function: ease-out; }
}

Animation Properties

PropertyDefaultDescription
animation-namenoneName of the @keyframes rule
animation-duration0sHow long one cycle takes
animation-timing-functioneaseSpeed curve per cycle
animation-delay0sWait before starting. Negative = start mid-animation
animation-iteration-count1Number of cycles. infinite = loop forever
animation-directionnormalnormal | reverse | alternate | alternate-reverse
animation-fill-modenoneStyles before/after animation (see below)
animation-play-staterunningrunning | paused — toggle with JS

Shorthand

/* animation: name duration timing delay iterations direction fill-mode */
animation: fadeUp 0.4s ease 0.1s 1 normal forwards;

/* Multiple animations */
animation: fadeUp 0.4s ease forwards, pulse 2s ease-in-out 0.5s infinite;

animation-fill-mode Explained

ValueBefore animationAfter animation
noneOriginal stylesOriginal styles (snaps back)
forwardsOriginal stylesLast keyframe styles (stays put)
backwardsFirst keyframe stylesOriginal styles
bothFirst keyframe stylesLast keyframe styles
/* Most common — element starts invisible, fades in and stays */
.fade-in {
  opacity: 0;
  animation: fadeIn 0.4s ease forwards; /* forwards keeps final state */
}
@keyframes fadeIn { to { opacity: 1; } }

Practical Examples

/* Staggered entrance animation */
.card { opacity: 0; animation: fadeUp 0.4s ease forwards; }
.card:nth-child(1) { animation-delay: 0.05s; }
.card:nth-child(2) { animation-delay: 0.1s; }
.card:nth-child(3) { animation-delay: 0.15s; }

/* Spinner */
@keyframes spin { to { transform: rotate(360deg); } }
.spinner { animation: spin 1s linear infinite; }

/* Floating effect */
@keyframes float {
  0%, 100% { transform: translateY(0); }
  50%       { transform: translateY(-10px); }
}
.mascot { animation: float 4s ease-in-out infinite; }

/* Pause on hover */
.card:hover .mascot { animation-play-state: paused; }