CSS animations are powered by the @keyframes rule, which defines named stages of a timeline and the styles an element should have at each stage. The syntax looks like @keyframes name { 0% { ... } 50% { ... } 100% { ... } }, where percentages mark keyframe positions. The keywords from and to are aliases for 0% and 100% respectively. Each keyframe selector can set any number of properties — transform, opacity, color, and so on — and the browser interpolates between them.
To apply an animation, the animation property is used together with @keyframes. The shorthand syntax is animation: name duration timing-function delay iteration-count direction fill-mode play-state, though only the first two are required. animation-name picks which @keyframes rule to use; without it, no animation runs. animation-duration sets the total length of one cycle, with a default of 0s that disables the animation. animation-iteration-count controls how many times the cycle repeats and can be a number or infinite, the default being 1. animation-direction sets the playback direction: normal, reverse, alternate (forward then backward), or alternate-reverse, defaulting to normal. A "ping-pong" effect is achieved with animation-direction: alternate.
animation-fill-mode determines what styles the element retains outside the animation runtime. Its values are none, forwards, backwards, and both. none (the default) means styles only apply while the animation is running; backwards applies the first keyframe's styles during any animation-delay period before the animation actually starts; forwards keeps the last keyframe's styles applied after the animation ends; both combines these behaviors. animation-play-state pauses or resumes the animation, accepting running or paused, and can be toggled on hover or via JavaScript.
animation-delay defers the start of the first iteration of an animation, which is different from transition-delay, which defers a single property change. A negative delay such as animation-delay: -1s starts the animation as if it had already been running, which is a useful trick to begin an animation mid-cycle. A common technique for staggering multiple animations is to give each element a different animation-delay, creating a cascading effect across a group. To loop seamlessly, set animation-iteration-count: infinite and make the 100% keyframe match the 0% keyframe so there is no visible jump. Note that animation-iteration-count controls how many times the cycle repeats and is independent of animation-duration, which controls the length of one cycle. JavaScript can react to the animationend event when an iteration finishes, and it can pause or restart animations by manipulating the animation property and forcing a reflow.
If a 0% or 100% keyframe is omitted, the browser uses the element's current style for that missing endpoint. Setting display: none on the element cancels any active animations or transitions; the animationend and transitionend events are not fired when this happens. To make a smooth slide-in from the left, for example, define @keyframes slideIn { from { transform: translateX(-100%); } to { transform: translateX(0); } } and apply it with a duration and easing.