How CSS Transitions Interpolate Property Changes

CSS transitions smoothly animate the shift between two states of an element rather than rendering an abrupt visual jump. When a style change is triggered—such as through a :hover state or an updated class—the browser determines intermediate values between the initial and target states over a defined duration. This process, known as interpolation, relies on mathematical formulas tailored to specific CSS data types and is governed by timing functions that map the progression of time to visual progress.

The Mechanics of Interpolation

Interpolation is the mathematical calculation of values situated between two known endpoints: the starting state (\(V_{start}\)) and the target state (\(V_{end}\)). When a transition is initiated, the browser marks the start time and monitors the elapsed time relative to the specified transition-duration.

At any given point during the transition, the browser computes a normalized time value (\(t\)) between 0.0 (start) and 1.0 (completion):

\[t = \frac{\text{elapsed time}}{\text{transition duration}}\]

This normalized time is passed into a timing function to calculate an output progress factor (\(p\)). The browser then applies linear interpolation (lerp) to determine the intermediate property value:

\[\text{Current Value} = V_{start} + (V_{end} - V_{start}) \times p\]

Property Types and Calculation Methods

Different CSS data types require distinct interpolation strategies:

  • Numerical Values and Lengths: Properties such as width, font-size, opacity, and padding interpolate scalar values directly. If units match (e.g., converting 10px to 100px), the calculation proceeds linearly on the raw numbers. If units differ (e.g., 10px to 5rem), the browser first computes the absolute pixel equivalent of both values before calculating the in-between frames.
  • Colors: Colors transition across individual channels. In standard sRGB transitions, the browser interpolates the red, green, blue, and alpha components separately: \[\text{Red}_{current} = \text{Red}_{start} + (\text{Red}_{end} - \text{Red}_{start}) \times p\] Modern CSS engines can also interpolate within perceptually uniform color spaces like Oklab or LCH to avoid muddy intermediate gray tones.
  • Transforms: Properties using transform (such as translate, rotate, and scale) interpolate individual transform functions directly when the function lists match. When transform lists differ in structure, browsers convert both states into \(4 \times 4\) transformation matrices, decompose them into translation, rotation, scale, and skew components, interpolate those components, and recompose the final matrix for each frame.
  • Discrete Properties: Properties without intermediate states (such as visibility or border-style) cannot be blended smoothly. For these, the browser switches values at \(p = 0.5\) or at the boundary of the transition depending on the property specifications.

The Influence of Timing Functions

While duration sets the overall timeframe, the transition-timing-function determines the pace of change. It adjusts the progress value (\(p\)) relative to the elapsed time (\(t\)):

  • Cubic Bézier Curves: Most continuous transitions rely on cubic Bézier curves defined by four points: \(P_0(0,0)\), \(P_1(x_1, y_1)\), \(P_2(x_2, y_2)\), and \(P_3(1,1)\). Keywords like ease, linear, and ease-in-out are predefined curves. By altering the tangent handles (\(P_1\) and \(P_2\)), the browser can simulate acceleration, deceleration, and spring-like physics where the progress temporarily exceeds \(1.0\).
  • Step Functions: Defined using steps(n, direction), this approach breaks the transition into a specific number of discrete intervals instead of continuous movement, holding each intermediate value for an equal portion of the duration.

Browser Execution and the Rendering Pipeline

Transitions execute within the browser's render loop, ideally synchronized with the display's refresh rate (commonly 60Hz to 120Hz).

Interpolation performance depends on which stage of the rendering pipeline a property affects:

  1. Layout properties (e.g., width, top, margin) force the browser to recalculate the document geometry on every frame, which is computationally expensive.
  2. Paint properties (e.g., background-color, color) require repainting elements without altering geometry.
  3. Composite properties (e.g., opacity, transform) bypass layout and paint entirely. The browser hands off the interpolation calculation to the GPU/compositor thread, ensuring 60+ frames per second even when the main JavaScript thread is busy.