CSS linear() Function

The CSS linear() function defines a custom animation or transition timing curve using a series of progress stops connected by straight lines.

It allows developers to control how an animated property progresses over time. Unlike the linear keyword, which produces a constant rate of change, linear() can describe complex timing effects, including acceleration, deceleration, pauses, and overshooting.

Syntax

linear(stop, stop, ...)
linear(output)
linear(output input-position)
linear(output input-position-1 input-position-2)

The function accepts two or more comma-separated progress stops. Each stop contains an output progress value and may include one or two input progress percentages.

For example:

.box {
  transition-timing-function: linear(0, 0.5, 1);
}

This defines three evenly distributed progress stops. Because their values form a straight diagonal, the result is equivalent to constant-speed linear easing.

Additional examples:

linear(0, 1)
linear(0, 0.8, 1)
linear(0, 0.5 30%, 1)
linear(0 0%, 0.7 40%, 1 100%)
linear(0, 1.2 70%, 1)
linear(0, 1 50%, 1 70%, 1)
linear(0, 1 40% 60%, 0)

Unlike many mathematical CSS functions, the arguments are separated by commas.

The function returns an <easing-function> value.

Parameters

The linear() function uses progress stops to define its timing curve.

Component Description Required
output A number representing the output progress at the stop. Yes
input-position A percentage indicating where the stop occurs in the input progress. No
input-position-2 An optional second position for the same output value. No

For example:

linear(0, 0.8 40%, 1)

This specifies:

  • An initial output value of 0.
  • An output value of 0.8 at 40% input progress.
  • A final output value of 1.

The browser connects the resulting points using straight-line segments.

Output values are numbers, while explicit input positions use percentages.

How It Works

The linear() function maps input progress to output progress.

Input progress represents how far the animation has advanced through its duration. Output progress determines how far the animated value has moved between its endpoints.

For example:

linear(0, 0.8 40%, 1)

At 40% of the animation duration, the timing function produces an output progress of 0.8.

If an element moves from 0 to 200 pixels, the timing function places it approximately 160 pixels along that movement at 40% input progress.

Between the specified stops, the browser interpolates linearly.

By adding more stops, developers can approximate complex easing curves using multiple straight-line segments.

The function controls the timing of interpolation, not the property's starting and ending values.

Progress Stops

A progress stop defines a point on the timing curve.

For example:

linear(0, 0.3 20%, 0.8 60%, 1)

This creates four stops:

Input Progress Output Progress
0%0
20%0.3
60%0.8
100%1

The browser connects these points with straight-line segments.

Each segment can have a different slope, producing different rates of change throughout the animation.

More stops provide finer control over the shape of the timing curve.

Input Progress

Input progress represents the position within the animation or transition duration.

It is expressed as a percentage:

linear(0 0%, 0.5 25%, 0.8 70%, 1 100%)

The percentages indicate when each output value is reached.

For example, with a two-second animation:

Input Progress Elapsed Time
0%0 seconds
25%0.5 seconds
70%1.4 seconds
100%2 seconds

These times assume normal playback without additional timing effects such as delays or playback-rate changes.

Input positions must progress in nondecreasing order after stop-position fixup. If an explicit position is less than a preceding position, it is raised to that preceding position.

Repeated input positions are permitted and can produce an instantaneous change in output progress.

Output Progress

Output progress determines the interpolated position between the animation's starting and ending values.

Common output values include:

Output Meaning
0Starting value
0.2525% of the interpolated change
0.550% of the interpolated change
1Ending value
1.220% beyond the ending value, when the property permits it
-0.220% before the starting value, when the property permits it

For example:

linear(0, 1.2 70%, 1)

The output rises beyond 1 before returning to the ending value.

Output progress is not restricted to the interval from 0 to 1.

However, the animated CSS property may clamp or otherwise limit the resulting value.

Automatic Stop Positions

Input percentages are optional. When they are omitted, the browser assigns positions automatically.

For example:

linear(0, 0.25, 0.75, 1)

With no explicit input positions, the stops are distributed evenly:

Stop Assigned Input Position
First0%
Second33.33%
Third66.67%
Fourth100%

When some positions are specified, omitted positions between them are distributed evenly across the available interval.

For example:

linear(0, 0.2, 0.5, 0.8 75%, 1)

The browser distributes the unspecified intermediate positions between the first stop at 0% and the explicitly positioned stop at 75%.

The first and last stops default to 0% and 100% when their positions are omitted.

Multiple Positions

A single output stop can include two input positions.

For example:

linear(0, 0.5 30% 60%, 1)

The output reaches 0.5 at 30% input progress and remains at 0.5 until 60% input progress.

This is equivalent to:

linear(0, 0.5 30%, 0.5 60%, 1)

Multiple positions provide a compact way to create flat sections in a timing curve.

For example:

linear(0, 1 40% 70%, 0)

The output reaches 1 at 40%, stays there until 70%, and then returns to 0.

Each stop accepts at most two input positions.

Overshooting

Overshooting occurs when the timing function produces an output progress outside the normal 0 to 1 interval.

For example:

linear(0, 1.25 70%, 1)

The output reaches 1.25 at 70% of the animation duration, then returns to 1.

This can create an overshoot effect when animating properties such as transform.

Another example moves below the starting value:

linear(0, -0.15 15%, 1)

The output briefly becomes negative before progressing toward the ending value.

For example:

.box {
  transition: transform 700ms linear(0, 1.25 70%, 1);
}
.box:hover {
  transform: translateX(200px);
}

During the transition, the element can move beyond its final position before settling at 200 pixels.

Overshooting is most useful with properties whose interpolated values can extend beyond the original endpoints.

Pauses and Sudden Changes

The linear() function can create pauses by keeping the same output value across an interval of input progress.

For example:

linear(0, 0.5 30% 60%, 1)

The output remains at 0.5 between 30% and 60% of the duration.

Sudden changes can be created by using different output values at the same input position:

linear(0, 0.3 50%, 0.8 50%, 1)

At 50% input progress, the output jumps from 0.3 to 0.8.

For example:

.box {
  animation-timing-function: linear(0, 0.3 50%, 0.8 50%, 1);
}

Repeated positions create discontinuities in the timing curve.

These effects can be useful for stylized motion, but abrupt changes should be used carefully to avoid distracting or uncomfortable animations.

Using Animations

The linear() function can be used with the animation-timing-function property.

For example:

.box {
  animation: slide 2s linear(0, 0.7 30%, 1);
}
@keyframes slide {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(200px);
  }
}

The element progresses quickly through the first 70% of the movement and then slows during the remaining time.

The timing function can also be written separately:

.box {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: linear(0, 0.7 30%, 1);
}

For animations with multiple keyframe intervals, the easing function applies to the relevant keyframe segment rather than necessarily controlling the entire animation as one continuous interval.

Use the animation-timing-function property to define how values progress between keyframes.

Using Transitions

The linear() function can also control CSS transitions.

For example:

.button {
  transform: scale(1);
  transition: transform 600ms linear(0, 1.15 70%, 1);
}
.button:hover {
  transform: scale(1.2);
}

The button grows beyond its final scale before settling at the target size.

The function can be assigned using the transition-timing-function property:

.button {
  transition-property: transform;
  transition-duration: 600ms;
  transition-timing-function: linear(0, 1.15 70%, 1);
}

The timing curve affects how the property moves between its starting and ending values.

Transitions begin when the computed value of an animatable property changes.

Using Custom Properties

CSS custom properties can store reusable linear() easing functions.

For example:

:root {
  --ease-custom: linear(0, 0.8 40%, 1);
  --ease-overshoot: linear(0, 1.2 70%, 1);
}
.card {
  transition: transform 500ms var(--ease-custom);
}
.button {
  transition: transform 700ms var(--ease-overshoot);
}

Using custom properties helps maintain consistent motion throughout a design.

The timing function can be changed in one location without updating every animation or transition declaration.

For example:

:root {
  --ease-custom: linear(0, 0.2 15%, 0.8 75%, 1);
}

All elements using var(--ease-custom) will use the updated curve.

linear() vs. linear

The linear() function and the linear keyword are related but not identical.

Feature linear() linear
TypeCustom easing functionPredefined easing keyword
Timing curveMultiple straight-line segmentsOne straight diagonal line
Custom stopsYesNo
OvershootingYesNo
PausesYesNo
Typical useCustom motionConstant-rate motion

For example:

transition-timing-function: linear;
transition-timing-function: linear(0, 1);

These produce equivalent constant-rate easing.

However:

transition-timing-function: linear(0, 0.8 30%, 1);

This creates a custom timing curve with a faster initial progression.

The linear keyword is sufficient when a constant rate of change is desired.

linear() vs. cubic-bezier()

The linear() and cubic-bezier() functions both define custom easing behavior.

Feature linear() cubic-bezier()
Curve constructionConnected straight-line segmentsOne cubic Bézier curve
Control valuesProgress stopsFour control-point coordinates
Number of control pointsVariableTwo internal control points
OvershootingSupportedSupported
Sudden jumpsSupported with repeated positionsNot produced by a continuous Bézier curve
Typical useComplex or sampled timing curvesSmooth easing curves

For example:

transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1);
transition-timing-function: linear(0, 0.15 10%, 0.5 30%, 0.85 60%, 1);

The two functions can produce similar motion, but their curves are constructed differently.

Use cubic-bezier() for a smooth curve controlled by two points, and linear() for detailed control using many stops.

linear() vs. steps()

The linear() and steps() functions can both produce nonuniform timing behavior, but they use different approaches.

Feature linear() steps()
Timing behaviorPiecewise linear interpolationDiscrete jumps
Custom progress stopsYesNo
Continuous segmentsYesNo
Sudden changesPossibleFundamental behavior
Typical useCustom motion and pausesFrame-by-frame or stepped changes

For example:

animation-timing-function: steps(4, end);
animation-timing-function: linear(0, 0.25 25%, 0.5 50%, 0.75 75%, 1);

The steps() function creates discrete jumps, while the linear() example connects its stops with continuous segments.

To create jumps with linear(), use repeated input positions with different output values.

Example

This example compares constant-speed linear easing with a custom linear() timing curve.

HTML:

<div class="linear-demo">
  <div class="linear-demo-row">
    <span>linear</span>
    <div class="linear-demo-track">
      <div class="linear-demo-box linear-demo-standard"></div>
    </div>
  </div>
  <div class="linear-demo-row">
    <span>linear()</span>
    <div class="linear-demo-track">
      <div class="linear-demo-box linear-demo-custom"></div>
    </div>
  </div>
</div>

CSS:

.linear-demo {
  max-width: 540px;
  margin: 0 auto;
}
.linear-demo-row {
  margin-bottom: 18px;
}
.linear-demo-row span {
  display: block;
  margin-bottom: 6px;
  font-size: 13px;
}
.linear-demo-track {
  height: 36px;
  background-color: #eeeeee;
  border: 1px solid #dddddd;
}
.linear-demo-box {
  width: 36px;
  height: 34px;
  background-color: #0066cc;
  animation-name: linear-demo-move;
  animation-duration: 3s;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
.linear-demo-standard {
  animation-timing-function: linear;
}
.linear-demo-custom {
  background-color: #198754;
  animation-timing-function: linear(0, 0.8 30%, 1);
}
@keyframes linear-demo-move {
  from { margin-left: 0; }
  to { margin-left: calc(100% - 36px); }
}
@media (prefers-reduced-motion: reduce) {
  .linear-demo-box {
    animation: none;
  }
}
Browser Result
linear
linear()

The blue box moves at a constant rate. The green box moves more quickly at the beginning and more slowly toward the end.

Both animations use the same duration and distance, but their timing curves produce different motion.

Bounce Example

This example uses output values above and below the ending position to create a bouncing effect.

HTML:

<div class="linear-bounce-demo">
  <div class="linear-bounce-box">Bounce</div>
</div>

CSS:

.linear-bounce-demo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 180px;
  background-color: #f1f3f5;
  overflow: hidden;
}
.linear-bounce-box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 90px;
  height: 50px;
  background-color: #0066cc;
  color: #ffffff;
  border-radius: 5px;
  font-size: 14px;
  animation: linear-bounce-motion 2s infinite;
  animation-timing-function: linear(0, 1.2 55%, 0.85 75%, 1);
}
@keyframes linear-bounce-motion {
  from { transform: translateY(-45px); }
  to { transform: translateY(45px); }
}
@media (prefers-reduced-motion: reduce) {
  .linear-bounce-box {
    animation: none;
  }
}
Browser Result
Bounce

The output first overshoots the ending position, moves back, and then settles at the final value.

The repeated animation restarts after each iteration. A production animation can use a different iteration count or direction depending on the intended effect.

Common Uses

The linear() function is useful when predefined easing keywords do not provide enough control.

Use Description
Custom easingDefine timing curves using multiple progress stops.
OvershootingMove beyond an endpoint before returning.
Bouncing effectsApproximate bounce or spring-like motion.
PausesHold an interpolated value during part of an animation.
Sudden changesCreate jumps using repeated input positions.
TransitionsControl how properties change between states.
Reusable motionStore timing curves in CSS custom properties.
Sampled curvesApproximate complex timing behavior with many line segments.

For example:

.panel {
  transition: transform 600ms linear(0, 0.15 10%, 0.85 65%, 1);
}

This produces a custom timing curve that changes its rate of progress across the transition.

Limitations

The linear() function has several important rules and limitations.

  • Each progress stop requires a numeric output value.
  • Input positions use percentages, not time units such as seconds.
  • Progress stops are separated by commas.
  • Each stop can contain no more than two input positions.
  • Stop positions are adjusted to maintain nondecreasing input progress.
  • Segments between stops are straight lines, not smooth Bézier curves.
  • Output values outside the 0 to 1 interval may be limited by the animated property.
  • Repeated input positions can produce abrupt jumps.
  • The function controls interpolation timing, not the animation's duration.
  • Older browsers may require a fallback timing function.
  • Complex motion should account for users who prefer reduced animation.

For example, this is valid:

animation-timing-function: linear(0, 0.8 40%, 1);

The following is invalid because the output progress is missing:

animation-timing-function: linear(0, 50%, 1);

The following is invalid because time units cannot replace input percentages:

animation-timing-function: linear(0, 0.8 1s, 1);

Use numeric output values and optional percentage positions to define valid stops.

Browser Support

The CSS linear() easing function is Baseline Widely available. It has been supported across major browser engines since December 2023.

Modern versions of Chrome, Edge, Firefox, Safari, and other major browsers support the function.

For example:

.box {
  transition-timing-function: linear(0, 0.8 40%, 1);
}

Older browsers may not recognize custom linear easing functions.

A fallback can be provided before the newer declaration:

.box {
  transition-timing-function: ease;
  transition-timing-function: linear(0, 0.8 40%, 1);
}

Browsers supporting linear() use the second declaration, while older browsers retain ease.

For current compatibility information, visit Can I Use? and search for CSS linear() easing function.

Specifications

The linear() easing function is defined in the CSS Easing Functions Level 2 .

The specification defines progress stops, automatic input positions, multiple positions, and piecewise linear interpolation.

Related CSS easing functions include cubic-bezier() and steps(), along with predefined easing keywords such as linear, ease, ease-in, ease-out, and ease-in-out.