CSS animation-timing-function Property

Beginner
7 min read
Updated: Oct 2026
3 examples
Live preview

Definition and Usage

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.

CSS Syntax

One easing function, or a comma-separated list with one function per animation name.

syntax.css
animation-timing-function: ease | linear | ease-in | ease-out | ease-in-out | cubic-bezier() | steps() | initial | inherit;

Property Values

ValueDescriptionTry it
easeDefault. Slower at the start and the end, faster in the middleTry it
linearEven speed for the whole trip. This keyword is not the linear() functionTry it
ease-inSlow start, then fastTry it
ease-outFast start, then slowTry it
ease-in-outSlow at both ends, faster in the middle, more even than easeTry it
cubic-bezier()Your own curve. The two x values must be from 0 to 1. The y values may go outside that and overshootTry it
steps()Equal time jumps. steps(4, end) holds, then jumps. end is the default. step-end is steps(1, end)Try it
initialSets this property to its default value, easeTry it
inheritCopies the parent's curve only. The name and the duration are not copiedTry it

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.

How to Use animation-timing-function

Give the animation a start, an end, and a duration. Then choose how that time is spent.

  1. Write an @keyframes rule with a from and a to. Point animation-name at it.
  2. Set animation-duration above 0s. That is the length of the trip. The curve does not change it.
  3. Set animation-timing-function. If you skip it, the browser uses ease.
  4. For two animation names, list two functions in the same order. One function is repeated for every name.
PieceRequired?Role
from and toYesThe curve fills the time between them
DurationYesHow long the trip lasts
FunctionDefault easelinear, ease-in, steps(), or your own curve
Comma listSeveral namesOne curve per name, in that order

Live Preview

The box travels the same distance in 2 seconds every time. Only the curve changes. Each choice replays the trip from the start.

The snap back to the start is the next loop. It is not part of the curve.

Preview
Box

animation-timing-function: ease

CSS Examples

Each snippet uses the same move. The line to study is animation-timing-function. Use Try It Yourself for a live editor.

Example 1 — Linear and Ease

Same distance, same 2 seconds. One speed is even. The default slows at both ends.

CSS
<style>
  @keyframes slide {
    from { transform: translateX(0); }
    to { transform: translateX(120px); }
  }
  div {
    width: 80px;
    height: 80px;
    background: #1d4ed8;
    animation-name: slide;
    animation-duration: 2s;
    animation-iteration-count: infinite;
  }
  .even { animation-timing-function: linear; }
  .soft { animation-timing-function: ease; }
</style>

<div class="even">Linear</div>
<div class="soft">Ease</div>
Try It Yourself

How It Works

  1. One trip. from and to move the box 120px. There is no middle stop, so one curve covers the whole 2 seconds.
  2. linear is even. The box covers about the same distance in the first second and the second second.
  3. ease is the default. It starts slower, speeds up, then slows into the end. Writing it out makes the comparison obvious.
  4. The snap is the loop. infinite sends the box back to the start for the next cycle. That jump is not the timing function.

Example 2 — Ease In and Ease Out

The slow part sits at the start, or at the end.

CSS
<style>
  @keyframes slide {
    from { transform: translateX(0); }
    to { transform: translateX(120px); }
  }
  div {
    width: 80px;
    height: 80px;
    background: #1d4ed8;
    animation-name: slide;
    animation-duration: 2s;
    animation-iteration-count: infinite;
  }
  .in { animation-timing-function: ease-in; }
  .out { animation-timing-function: ease-out; }
</style>

<div class="in">In</div>
<div class="out">Out</div>
Try It Yourself

How It Works

  1. Same trip. Both boxes move 120px in 2 seconds.
  2. ease-in waits, then rushes. Most of the distance happens late.
  3. ease-out rushes, then settles. Most of the distance happens early, and the box eases into the end.
  4. The name says where it is slow. In is slow at the start. Out is slow at the end. ease-in-out is slow at both ends.

Example 3 — Steps

Four jumps instead of a slide. A linear box sits beside it so the holds are easy to see.

CSS
<style>
  @keyframes slide {
    from { transform: translateX(0); }
    to { transform: translateX(120px); }
  }
  div {
    width: 80px;
    height: 80px;
    background: #1d4ed8;
    animation-name: slide;
    animation-duration: 2s;
    animation-iteration-count: infinite;
  }
  .even { animation-timing-function: linear; }
  .jump { animation-timing-function: steps(4, end); }
</style>

<div class="even">Even</div>
<div class="jump">Steps</div>
Try It Yourself

How It Works

  1. Same 120px trip. linear glides. steps does not pass through the positions in between.
  2. Four equal slices. steps(4, end) splits the 2 seconds into four holds of half a second.
  3. end jumps late. The box holds a stop, then jumps when that slice ends. It starts on the first frame, still.
  4. 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.

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 Chrome 43+ · 3+ with -webkit-
Full support
Mozilla Firefox 16+ · 5+ with -moz-
Full support
Apple Safari 9+ · 4+ with -webkit-
Full support
Microsoft Edge 12+
Full support
Opera 30+ · 15+ with -webkit-
Full support
Samsung Internet 4+
Full support
Internet Explorer 10+
Full support
animation-timing-function Widely 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.

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.

Next: aspect-ratio

Keep an element at a chosen width-to-height ratio.

aspect-ratio tutorial →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

8 people found this page helpful