Skip to main content
Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.

Animation Timing-Functions Get Applied Per-Keyframe In CSS

By Ben Nadel on
Tags: HTML / CSS

A couple of weeks ago, I looked at creating a simple slide-show using dynamic keyframe animations in Angular 10.0.9. In the video for that demo, I mentioned that my approach was somewhat limited because the timing-function wasn't granular enough. As it turns out, my assumption of granularity was completely wrong. In fact, as I just learned from Una Kravets on the Animations episode of the CSS Podcast, the animation-timing-function property is applied on a per-keyframe basis. To help correct my poor mental model, I put together a small demo showcasing this per-keyframe granularity.

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

To demonstrate that the animation-timing-function within a CSS animation is applied on a per-keyframe basis, I am going to use cubic-bezier() function that moves a dot across the screen with a sort-of "bouncing" effect. This way, we can see that the dot "bounces" beyond the bounds of each keyframe configuration - not just beyonds the bounds the overall animation.

In the following CSS animation, the dot will rest at about 1/3 the horizontal distance; then again at about 2/3 the horizontal distance. At each resting point, we should see the cubic-bezier() animation-timing-function "bounce" the dot beyond the target left setting.

<!doctype html>
<html lang="en">
	<meta charset="utf-8" />

		Animation Timing-Functions Get Applied Per-Keyframe In CSS

		Animation Timing-Functions Get Applied Per-Keyframe In CSS

	<style type="text/css">

		.track {
			border: 1px solid red ;
			border-radius: 100px ;
			height: 100px ;
			position: relative ;

		.marker {
			background-color: red ;
			bottom: 0px ;
			position: absolute ;
			top: 0px ;
			width: 1px ;

		.dot {
			background-color: #212121 ;
			border-radius: 80px ;
			height: 80px ;
			left: 10px ;
			position: absolute ;
			top: 10px ;
			width: 80px ;
			z-index: 2 ;
				In order to demonstrate that the timing-function executes per-keyframe,
				I'm going to use an exaggerated cubic-bezier configuration that "bounces"
				the dot past the final "left" value of each keyframe.
			animation-direction: alternate ;
			animation-duration: 10s ;
			animation-iteration-count: infinite ;
			animation-name: box-animation ;
			animation-timing-function: cubic-bezier( .55, -0.64, .42, 1.63 ) ;

		@keyframes box-animation {
			from, 5% {
				left: 10px ;
			25%, 40% {
				left: 30% ;
			60%, 75% {
				left: 70% ;
			95%, to {
				left: calc( 100% - 90px ) ;


	<div class="track">
		<div class="dot">
			<br />

		<!-- These markers help show the movement of the dot. -->
		<div class="marker" style="left: calc( 30% + 40px ) ;"></div>
		<div class="marker" style="left: calc( 70% + 40px ) ;"></div>


And, when we run this CSS animation in the browser, we get the following output:

A dot moved across the screen using a bouncing animation per keyframe in CSS.

As you can see, the dot "bounces" beyond the target left alignment of each CSS keyframe. That's because the animation-timing-function is being applied on a per-keyframe basis - not to the entire animation life-span. This is a small but critical difference in how keyframe animations work. And now, hopefully, I'll remember this going forward.

Reader Comments


As a fast-follow to this post, I wanted to demonstrate that CSS Animation timing-functions can actually be changed per-keyframe:

That's actually the piece of information that Una mentioned in the CSS Podcast - that the animation-timing-function can be overridden within a key-frame; which, in turn, led me to understand that the timing-function is also applied per-keyframe as well. Overall, it seems that CSS Animations are just a lot more powerful and dynamic than I had given them credit for.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Blog
Live in the Now
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.