Tintin rocketship

Web animation is most often created between two points: from and to a state, or between position A and B. Moving elements in arcs, ellipses and circles is less frequently used, but it’s a very valuable thing to know.

Circles

Circles are the easiest option. The key – which everything else here will follow – is to displace the element’s transform-origin. (All CSS is shown without vendor prefixes for clarity).

div#redball {
	width: 50px; height: 50px;
	border-radius: 50%;
	background: red;
	transform-origin: 200% center; 
}

… setting the origin point for every transform will be 200px to the right of the element:

HTML element with displaced transform-origin

Which means that rotation of the element will be around this displaced point:

@keyframes circle { 
	to { transform: rotate(1turn); } 
}
div#redball {
	animation: circle 2s infinite; 
}

The problem is the default easing on the animation: if you want the motion to appear continuous, linear motion must be used:

div#redball {
	animation: circle 2s infinite linear; 
}

This creates a seamless circular animation.

Arcs

Illustration of pendulum

Linear animation applied to motion in an arc will usually look wrong, and too mechanical. Making a pendulum motion, like my recent “hypnotic logo animation”, require easing at both ends of the motion, together with restricting the range of rotation:

@keyframes sway {
	to { transform: rotate(30deg); }
}
#watch {
	transform-origin: center top;
	transform: rotate(-30deg);
	animation: sway 2.2s infinite alternate ease-in-out;
}
Illustration of card fan

This kind of animation is frequently used as a reveal: my “CSS card fan UI” is a good example.

Ellipses

The most challenging form of motion is the natural movement of the universe: ellipses. The easiest method I know of to achieve this is to “layer” the animation movement: moving an element up and down in half the phase that it moves in a circle. To achieve this, the element is wrapped inside a container:

<figure>
	<div id="redball"></div>
</figure>

And each element animated separately:

@keyframes circle { 
	to { transform: rotate(1turn); } 
}
@keyframes updown {
	to { transform: translateY(200px); } 
}
figure {
	animation: updown 1s infinite ease-in-out alternate;
}
div#redball {
	width: 100px; height: 50px;
	border-radius: 50%; background: red;
	transform-origin: center 300%;
	animation: circle 2s infinite linear;
}

The up-down motion extends the circular animation into an ellipse, with the extent of the vertical or horizontal motion determining the major axis of the elliptical shape. ease-in-out is used to smooth the motion, which would otherwise form a rounded diamond figure; alternate is used to ensure that the vertical motion repeats back and forth smoothly. Note the half-time measurement on the up-down animation as opposed to the circle animation.

Photograph by Jaime Junior, licensed under Public Domain.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/sjbrw