CSS transition-timing-function Property
This property specifies the speed curve of a transition effect, allowing you to change how fast an element evolves over the duration of the change.
| ease | Starts slow, speeds up in the middle, and then slows down at the end. |
| linear | Maintains the exact same speed from the beginning to the end of the transition. |
| ease-in | Starts the transition at a slow pace and accelerates until the end. |
| ease-out | Starts the transition at a fast pace and decelerates until the end. |
| ease-in-out | A symmetrical timing function that starts and ends slowly. |
| step-start | Causes the transition to skip immediately to the final state. |
| step-end | Causes the transition to stay at the initial state until the duration is complete. |
| <steps()> | Divides the transition into a specific number of equal-sized jumps or intervals. |
| <cubic-bezier()> | Defines a custom velocity curve using four numerical coordinates between 0 and 1. |
Code Examples
A basic example showing a button that smoothly expands using an ease-in-out timing function on hover.
<style>
.btn {
width: 150px;
padding: 10px;
background-color: #3498db;
border: none;
color: #ffffff;
transition-property: width;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
}
.btn:hover {
width: 250px;
}
</style>
<button class="btn">Hover Me</button>An advanced example using JavaScript to trigger a transition with a custom cubic-bezier curve that creates a bounce effect.
<style>
#box {
width: 50px;
height: 50px;
background-color: #e74c3c;
position: relative;
left: 0px;
transition: left 1s;
}
</style>
<div id="box"></div>
<button onclick="moveIt()">Slide with Custom Curve</button>
<script>
function moveIt() {
const el = document.getElementById("box");
/* Using a custom cubic-bezier for a 'back-and-forth' bounce feel */
el.style.transitionTimingFunction = "cubic-bezier(0.68, -0.55, 0.27, 1.55)";
el.style.left = el.style.left === "300px" ? "0px" : "300px";
el.style.backgroundColor = "#2ecc71";
}
</script>Pro Tip
You can use the "steps()" function to create a frame-by-frame animation style. This is perfect for sprite sheets or making a loading bar look like it is filling up in distinct blocks. Instead of a smooth slide, the element will jump in increments, which is a great way to achieve a retro or digital look without using complex JavaScript.
Deep Dive
Think of this property as the personality of your animation. If a transition is a car trip, the duration is how long it takes, but the timing function is how the driver uses the pedals. "linear" is like cruise control on a flat highway—boring and mechanical. "ease-in" is like flooring the gas from a stoplight, while "ease-out" is like gently braking as you pull into a driveway. Technically, the browser uses Bézier curves to calculate the interpolation of property values. By default, it uses "ease", which feels natural to the human eye because most things in the physical world don't start or stop instantly at full speed.
Best Practices
Use "ease-out" for elements entering the screen to make them feel like they are gracefully arriving. Use "ease-in" for elements leaving the screen so they appear to gain momentum as they exit. For standard UI interactions like button hovers, "ease" or "ease-in-out" usually provide the most professional feel. Avoid "linear" for movement unless you are creating a looping background or a specific mechanical effect, as it often looks robotic and cheap.
Common Pitfalls
A common mistake is thinking this property handles the duration of the animation; it only handles the speed curve. If you don't define a "transition-duration", this property does nothing because the change happens instantly. Also, be careful with custom "cubic-bezier" values; if you use values outside the 0 to 1 range, the element might "bounce" or overshoot its destination, which can look glitchy if not intended.
Accessibility
Fast or erratic timing functions can trigger motion sensitivity or vestibular disorders in some users. Always wrap your complex transitions in a "prefers-reduced-motion" media query to provide a simpler experience for those who need it. Ensure that the timing doesn't make critical content disappear so quickly that a user cannot perceive the change.
Dev Data Table: transition-timing-function property
| default | ease |
| animatable | no |
| inherited | no |
| experimental | no |
| year_intro | 2009 |
| year_standard | 2013 |
| js_syntax_1 | element.style.transitionTimingFunction = "ease-in-out"; |
| js_syntax_2 | element.style.setProperty("transition-timing-function", "cubic-bezier(0.1, 0.7, 1.0, 0.1)"); |
| js_note | When setting this property via JavaScript, the value must be a string representing a valid CSS timing keyword or cubic-bezier function. |
| browsers | { "Chrome": 26, "Edge": 12, "Firefox": 16, "Safari": 6.1, "Opera": 12.1, "Chrome Android": 26, "Safari on iOS": 7, "Samsung Internet": 1.5, "Opera Mobile": 12.1 } |