@keyframes
@keyframes <name> { from { … } <percentage> { … } to { … } }
A named course of an animation: which property values apply at the start, at the end and at any intermediate steps. It does not start anything by itself – it is used by the animation property with this name.
Values
- from and to – the start and the end, the same as
0%and100%. - percentages – intermediate steps in the range 0 to 100%. Positions with the same values can be joined with a comma:
0%, 100% { … }. - animation-timing-function inside a keyframe – the timing function for the segment from this keyframe to the next one.
Examples
Bouncing – three keyframes, the start and the end joined with a comma:
.ball {
animation: bounce 0.8s ease-in-out infinite;
}
@keyframes bounce {
0%, 100% { translate: 0 0; }
50% { translate: 0 -20px; }
}
Even a single keyframe is enough. The browser fills in the missing to from the ordinary styles of the element, so the animation ends exactly where the element normally is – including its opacity of 0.9:
.message {
opacity: 0.9;
animation: slide-in 0.3s ease-out;
}
@keyframes slide-in {
from {
opacity: 0;
translate: 0 -100%;
}
}
A timing function in individual keyframes – the fall accelerates, the rise after the bounce decelerates:
.ball {
animation: jump 1s both;
}
@keyframes jump {
0% {
translate: 0 -60px;
animation-timing-function: ease-in;
}
60% {
translate: 0 0;
animation-timing-function: ease-out;
}
80% {
translate: 0 -15px;
animation-timing-function: ease-in;
}
100% { translate: 0 0; }
}
Things to watch out for
- Declarations with
!importantare ignored inside@keyframes– the browser drops them, the other declarations of the keyframe still apply. - Two
@keyframesrules with the same name are not merged: the whole last one applies. That can be used – a rule inside@mediawritten later replaces the animation of the same name, for example forprefers-reduced-motion. - Properties that cannot change smoothly (for example
justify-content) change in one step halfway through the segment in an animation. - The name is case-sensitive and must not be
none. - Without a
fromortokeyframe the missing values are taken from the ordinary styles of the element – the animation thus continues smoothly from the state the element is in.
Browser support
Baseline – widely available: in all major browsers since September 2015, considered widely available since March 2018. Since version: Chrome 43, Firefox 16, Safari 9. As of October 2026 (MDN browser-compat-data).
Related:
animation
cubic-bezier() and steps()
transition
prefers-reduced-motion