Skip to main content
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Jeff Kunkel
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Jeff Kunkel@Nerdtastic91686 )

Animation Timing-Functions Get Applied Per-Keyframe In CSS

By on

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.

Want to use code from this post? Check out the license.

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.

Post A Comment — I'd Love To Hear From You!

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.