Skip to main content

Animation and Transition Timing

CSS transitions and animations don't just happen over a certain duration; they also follow a speed curve, which defines how quickly the animation starts, accelerates, and decelerates throughout its run time. This speed control is managed by the timing function.

The properties used are:

  • transition-timing-function (for simple transitions)
  • animation-timing-function (for keyframe animations)

1. Standard Timing Keywords​

The simplest way to control animation speed is by using one of the five standard keywords. Each keyword is a predefined implementation of the more complex cubic-bezier() function.

KeywordDescriptionCurve Behavior
ease (Default)Starts slowly, speeds up quickly in the middle, and ends slowly.Recommended for most smooth UI interactions.
linearMaintains a constant speed from start to finish.Useful for continuous, cyclical animations (like a spinner).
ease-inStarts slowly and steadily accelerates until the end.Gives the feeling of an element accelerating away from the user.
ease-outStarts quickly and steadily decelerates until the end.Gives the feeling of an element slowing to a stop.
ease-in-outStarts and ends slowly, with a fast middle section.Symmetrical, smooth motion in both directions.

Example Usage​

styles.css
.box-in {
/* Starts slow, ends fast */
transition-timing-function: ease-in;
}

.box-linear {
/* Consistent speed */
animation-timing-function: linear;
}

2. Customizing with cubic-bezier()​

The cubic-bezier(n, n, n, n) function gives you complete control over the speed curve. It accepts four numerical parameters between 0 and 1, which define the coordinates of two control points (P1P_1 and P2P_2) on a BΓ©zier curve.

The curve charts the progress of the animation (Y-axis, from 0 to 1) against the time elapsed (X-axis, from 0 to 1).

  • P0P_0: Fixed at the start of the animation (0, 0).
  • P3P_3: Fixed at the end of the animation (1, 1).
  • P1P_1: Control point one, defined by (x1,y1)(x_1, y_1).
  • P2P_2: Control point two, defined by (x2,y2)(x_2, y_2).

Syntax​

styles.css
/* Custom Bezier curve for an aggressive, fast start and slow finish */
transition-timing-function: cubic-bezier(0.8, 0.1, 0.2, 0.9);

You can use online tools (like cubic-bezier visualizers) to experiment with these four values and create highly customized motion.


3. Discrete Movement with steps()​

For animations that need to jump between states rather than transition smoothly, you use the steps() function. This is ideal for things like sprite-based animation, blinking effects, or simulating a clock with discrete ticks.

Syntax​

The function requires two parameters:

styles.css
steps(number_of_steps, step_position);
  1. number_of_steps: The total number of equally spaced intervals the animation will pause during its duration.
  2. step_position: Defines where the jump occurs relative to the interval.
    • end (Default): The change happens at the end of each time interval (holds for the full interval, then jumps).
    • start: The change happens at the beginning of each time interval (jumps immediately, then holds).

Example: Stepped Clock Hand​

If an animation runs for 60 seconds and you want it to jump 60 times (once per second):

styles.css
animation: tick 60s steps(60, end);

The animation will run in 60 discrete jumps over 60 seconds.


Interactive Timing Function Demo​

The three boxes below execute the same translateX(200px) transition over the same duration, but each uses a different timing function, demonstrating how the speed curve dramatically changes the feel of the movement.

In this demo, hovering over the container triggers the translation of each box. You can see how the different timing functions affect the speed and feel of the movement.