Inertia & Motion Blur

  • Bill murray
    Bill Murray
    Actor
  • Bill murray
    Bill Murray
    Actor
  • Bill murray
    Bill Murray
    Actor
  • Bill murray
    Bill Murray
    Actor
  • Bill murray
    Bill Murray
    Actor
  • Bill murray
    Bill Murray
    Actor

- 3 min read

Inspiration for this experiment came from a dribbble shot created with After Effects. Although we’ve come to a point where we can appropriately animate elements with the help of CSS animation and Javascript - we’re nowhere near the capabilities of what you can produce in After Effects. We're restricted by a number of things that aren't yet available to us in CSS, but it doesn't mean we can't try to emulate the effects.

The motion that inspired this experiment, the inertia effect in this Dribbble shot by Barthelemy Chalvet.

There have been some powerful animation libraries, such as Velocity, Bounce, Tremula, and GreenSock which have built upon what's possible with motion by leveraging the power of the matrix transform, but as a personal challenge I wanted to discover just how far it could go using almost purely CSS to style the animation.

I also believe it's a good practice to use the tools you have before you take a helping hand from a library or framework, as I learnt long ago with Flash and its associated 3d frameworks, frameworks can be a fork in the road to which no standards exist and are not always so interchangeable or useful later on down the track. Exercises like these are good to understand capability, more than they are to produce a production-ready prototype.

One of the most effective tools I find for understanding how to approach an animation with code is to take apart and reverse engineer the animations, more complex animations can often be broken down to smaller parts, which together make up a more interesting whole.

Most of what we see is actually the perception of something happening, motion blur isn't really motion blur - it just looks like motion blur, we're not really creating inertia - we're just pushing objects around with different timing, when you accept that you can start to play around with different properties to achieve the perception you need.

Creating Inertia

To create the perception of Inertia we need to move an element slightly out of sync with the objects within it, this provides us with a jelly-like wobble effect where the objects inside finish their movement slightly after the objects outside.

						

	/* To make the inertia possible, we need to both stretch and move the element */

	@keyframes inertiaUp {

		0% {
			/* start from it's initial scale */
			transform: scaleY(1);

		}

		50% {

			/*
			   stretch on the Y axis, and move down 1em -
			   against the grain of the transition which is moving up
			*/

			transform: scaleY(1.2) translateY(1em);

		}

		100% {

			/* end on it's initial scale */
			transform: scaleY(1);

		}

	}

	/* We want to apply different timing to the object that sits
	   within the list item so that when the object moves the
	   inertia animation happens slightly afterwards */

	.js-moving-up .d-list-moving-item > div {

		animation:inertiaUp 7s 0.1s ease-in-out forwards;

	}

						

					

Bending the element

Since we don’t currently have a way to bend an element in CSS properly, we have to fake this by animating the border-radius quickly and extending it beyond what you can see with overflow:hidden.

						
	/* To create the appearance of bending,
	   we apply a border radius of 50% mid way through the animation, then reset

	*/
	@keyframes bendy {

		0% {

			border-radius:0%

		}
		40% {

			border-radius:50%;

		}

		100% {

			border-radius:0%;

		}
	}

	/* Our line at the bottom is an :after pseudo element
	   rather than a simple border
	   so we have more control over it when animating
	*/

	.js-moving-up .d-list-moving-item:after {

		animation:bendy 1s forwards;

	}
						
					

More smoke & mirrors: blurring motion

At the time of writing this experiment there is no great way to blur motion in CSS. Motion blurring in CSS had to be faked. To fake something that doesn’t yet exist it’s effective to take apart what is actually happening frame by frame when motion blurring occurs.

What we find is that an object generally stretches slightly, in this case on the Y-Axis, it loses some opacity, and it leaves a wake or ghost of itself behind as it moves. We have properties in CSS which we can animate together to achieve this effect.

Although there is technically a way you can blur in CSS, you can’t blur in a direction like you could with Flash or After Effects - and it’s incredibly CPU intensive, if you try to move an element that’s blurred expect it to look incredibly janky, that being said this solution isn’t necessarily the most performant one either. Our most effective tools for motion blurring with CSS are shadows, box-shadow and text-shadow.

						

	/* to blur the object in motion we add text-shadow */

	@keyframes motionBlurTextUp {

		0% {
					/* start from a transparent white */
					text-shadow: 0 0 0 rgba(255, 255, 255, 0);

		}

		50% {
					/* become fully visible but with a long shadow */
					text-shadow: 0px 4px 4px rgba(255, 255, 255, 1);

		}

		100% {
					/* reset to transparent white */
					text-shadow: 0 0 0 rgba(255, 255, 255, 0);

		}

	}

	/* And apply the toggled javascript class (js-moving-up) to the list moving */

	.js-moving-up .d-list-moving {

		/* Apply the animation and its effects permanantly when it's finished */
		animation: motionBlurTextUp 0.7s 0.1s ease-in-out forwards;


	}
						

					

In the future

I'm looking forward to playing with the shape-inside and shape-outside properties of CSS Shape and seeing what can be achieved animating shapes to produce a similar effect to the bending of the object.

I'm not holding my breath for motion blurring effects in CSS, a simple blur animating from 0 to a blurred state is currently one of the slowest animatable properties I've encountered, so we'll just have to settle for nothing or the hacks for a few years.

For the time being, the most impressive results I've seen in the browser for this sort of thing have been using Canvas: such as this incredible Jelly navigation demo.