The animation-timing-function property sets how an animation spends its time between keyframes. linear keeps one speed. ease is slower at the ends. steps() jumps from stop to stop. The duration stays the same.
The initial value is ease, not linear. The property is not inherited, and it is not animatable. It applies to any element, including ::before and ::after. With one from and one to, the curve covers that whole trip. A middle keyframe splits the curve into separate pieces.
Standard-track.
Not deprecated and not experimental. Keywords, cubic-bezier(), and steps() with start or end have been widely available since September 2015. jump-* positions need Chrome 77, Firefox 65, or Safari 14. The linear() function, which is not the linear keyword, needs Chrome 113, Firefox 112, or Safari 17.2.
Syntax
CSS Syntax
One easing function, or a comma-separated list with one function per animation name.
unset equals initial here, so it is ease. revert uses the user-agent value, which is also ease. step-start is steps(1, start): one jump at the beginning.
Approach
How to Use animation-timing-function
Give the animation a start, an end, and a duration. Then choose how that time is spent.
Same 120px trip.linear glides. steps does not pass through the positions in between.
Four equal slices.steps(4, end) splits the 2 seconds into four holds of half a second.
end jumps late. The box holds a stop, then jumps when that slice ends. It starts on the first frame, still.
end is the default.steps(4) means the same thing. start would jump at the beginning of each slice instead.
Edge Cases & Pitfalls
If the curve looks wrong, one of these is usually why.
100%
A function on the last keyframe is unused
Inside @keyframes, the function controls the trip to the next keyframe. Nothing follows 100% or to, so a function there never runs. Put it on from, or set it on the element.
ease
The default is ease, not linear
If you omit the property, the ends are slower. Set linear when you want one speed. A middle keyframe also splits the curve, so each segment eases on its own.
short
The shorthand resets the curve to ease
animation: slide 2s infinite leaves out the timing function, so it becomes ease. Put linear in the shorthand, or set this property after it.
x
cubic-bezier() drops an x outside 0 to 1
The first and third numbers are horizontal. They must be from 0 to 1, or the declaration is ignored. The second and fourth numbers are vertical. They may go past 0 and 1, and the value then overshoots before it settles.
new
jump-* and linear() are newer
steps(4, end) matches the 2015 baseline. jump-end needs a newer browser. linear() with stops is newer still, and it is not the linear keyword. A fast loop can also be hard to read. prefers-reduced-motion is how a visitor asks for less motion.
Compatibility
Browser Support
animation-timing-function is a browser animation property. Node.js, Deno, and Bun do not apply it.
✓ Baseline · Since Sep 2015
animation-timing-function
Keywords, cubic-bezier(), and steps() with start or end: Chrome 43+, Firefox 16+, Safari 9+, Edge 12+, Opera 30+. Internet Explorer 10+. Samsung Internet 4+.
98%Unprefixed support
Google Chrome43+ · 3+ with -webkit-
Full support
Mozilla Firefox16+ · 5+ with -moz-
Full support
Apple Safari9+ · 4+ with -webkit-
Full support
Microsoft Edge12+
Full support
Opera30+ · 15+ with -webkit-
Full support
Samsung Internet4+
Full support
Internet Explorer10+
Full support
animation-timing-functionWidely supported
Bottom line: Keywords, cubic-bezier(), and steps(n, start) or steps(n, end) are safe in current browsers and in Internet Explorer 10. jump-start, jump-end, jump-none, and jump-both need Chrome 77, Firefox 65, or Safari 14. The linear() function needs Chrome 113, Firefox 112, or Safari 17.2.
Remember
Key Takeaways
Role: spread the animation's progress inside the duration. It does not change the duration.
Default:ease, slower at the ends. linear is the even keyword. You have to set it.
Where it applies: between keyframes. A function on 100% is never used.
Custom and steps:cubic-bezier() x values stay from 0 to 1. steps(4, end) jumps. The property is not inherited.
One line:animation-timing-function decides how the move is spread across the duration, from an even linear slide to a steps() jump.
Frequently Asked Questions
It sets how progress is spread across one animation cycle. ease starts and ends slower. linear keeps one speed. steps jumps between stops. It does not change how long the cycle lasts.
The initial value is ease, not linear. The property is not inherited, and it is not animatable.
No. animation-duration is the length of the cycle. The timing function only decides how much of the move happens early or late inside that time.
The function on a keyframe controls the trip from that keyframe to the next one. There is no next keyframe after 100%, so that function is never used.
The keyword linear is an even speed and has been widely available since 2015. linear() is a newer function that takes a list of stops, such as linear(0, 0.5, 1). It needs Chrome 113, Firefox 112, or Safari 17.2.
Unprefixed support for the keywords, cubic-bezier(), and steps() with start or end is Chrome 43+, Firefox 16+, Safari 9+, Edge 12+, and Opera 30+. Internet Explorer 10 and Samsung Internet 4 also support those values. It is a browser property. Node.js, Deno, and Bun do not apply it.