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:
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

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;
}

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