Hey there, CSS fans! This is the third part of a 3D series. The first one is here, the second is here, start from there if you missed any of them.
Before your character takes a single step, there’s one thing it absolutely needs: a skeleton.
In CSS animation, the skeleton isn’t bones and cartilage — it’s HTML structure and transform-origin
. It’s the thing that makes your character move like a character and not like a stack of divs having an existential crisis.
Watch video
Why Your Character Needs a Skeleton
Imagine animating a chicken. You want it to jump. You’ve already built it, colored it, and now… it’s time to move.
Without a skeleton, that means animating each part of the chicken individually. The head, the wings, the legs — all getting their own keyframes. It’s like micromanaging limbs in five timelines at once.
See animation madness to make this chicken just jump
@keyframes head {
0%, 85%, 100% { translate: 0em 0em 0em; }
20%, 80% { translate: 0em 0em -1em; }
50%, 60% { translate: 0em 0em 5em; }
}
@keyframes beak {
0%, 85%, 100% { translate: 2em 7em 4em; }
20%, 80% { translate: 2em 7em 3em; }
50%, 60% { translate: 2em 7em 8em; }
}
@keyframes wattle {
0%, 85%, 100% { translate: 2em 7em 2em; }
20%, 80% { translate: 2em 7em 1em; }
50%, 60% { translate: 2em 7em 6em; }
}
@keyframes comb {
0%, 85%, 100% { translate: 2em 2em 8em; }
20%, 80% { translate: 2em 2em 7em; }
50%, 60% { translate: 2em 2em 13em; }
}
@keyframes body {
0%, 85%, 100% { translate: 0em -3em -5em; }
20%, 80% { translate: 0em -3em -6em; }
50%, 60% { translate: 0em -3em 0em; }
}
@keyframes tail {
0%, 85%, 100% { translate: 1em -5em -5em; }
20%, 80% { translate: 1em -5em -6em; }
50%, 60% { translate: 1em -5em 0em; }
}
@keyframes wing-left {
0%, 85%, 100% { translate: -2em 0em -4em; }
20%, 80% { translate: -2em 0em -5em; }
50%, 60% { translate: -2em 0em 1em; }
}
@keyframes wing-right {
0%, 85%, 100% { translate: 6em 0em -4em; }
20%, 80% { translate: 6em 0em -5em; }
50%, 60% { translate: 6em 0em 1em; }
}
@keyframes knee-right {
0%, 20%, 80%, 100% { translate: 5em 2em -8em; }
50%, 60% { translate: 5em 2em -3em; }
}
@keyframes knee-left {
0%, 20%, 80%, 100% { translate: 0em 2em -8em; }
50%, 60% { translate: 0em 2em -3em; }
}
@keyframes foot-right {
0%, 20%, 80%, 100% { translate: 4em 1em -9em; }
50%, 60% { translate: 4em 1em -4em; }
}
@keyframes foot-left {
0%, 20%, 80%, 100% { translate: -1em 1em -9em; }
50%, 60% { translate: -1em 1em -4em; }
}
@keyframes finger-one {
0%, 20%, 80%, 100% { translate: -1em 4em -9em; }
50%, 60% { translate: -1em 4em -4em; }
}
@keyframes finger-two {
0%, 20%, 80%, 100% { translate: 1em 4em -9em; }
50%, 60% { translate: 1em 4em -4em; }
}
@keyframes finger-three {
0%, 20%, 80%, 100% { translate: 4em 4em -9em; }
50%, 60% { translate: 4em 4em -4em; }
}
@keyframes finger-four {
0%, 20%, 80%, 100% { translate: 6em 4em -9em; }
50%, 60% { translate: 6em 4em -4em; }
}
Now imagine that chicken needs to dance. No thanks.
A proper HTML skeleton saves you from this nightmare. It turns chaos into structure, and lets you focus on how your character moves — not how to keep it from falling apart.
The Chicken’s Skeleton
Let’s break down our chicken’s structure. Start from the body, then nest all the connected parts — like joints in real anatomy.
Each moving part is nested inside the one it’s attached to. Shoulder inside the body, arm inside the shoulder, hand inside the arm, finger inside the hand, and so on.
Want to add a hat? Drop it in the head element. A sword? Goes in the hand element. The HTML is the skeleton.
Let’s talk joints
Every animated element transforms (rotates) from one pont. In CSS, that point is transform-origin
.
By default, it’s in the center of the element. But for a character, that’s usually wrong. Your chicken’s wing doesn’t flap from the middle. You’ll need to manually set the anchor point — usually at the joint.
- Rounded character joints are circles.
- Cubic character joints are corner or center points.
- Realistic character joints are spheric.
Position transform-origin
based on how the character would move in real life. It sounds like overkill — it’s not. It’s what makes movement feel natural.
Animation Magic
Here’s the cool part: when you nest joints correctly, you only have to animate one thing. If you don’t nest? You’re stuck micromanaging every angle on every frame. Nightmare.
Compare these two examples: the one you already saw before and the one with a proper nesting.
CSS animation doesn’t have to be hard — just smart.
Want That Wiggly, Spaghetti-Limb Vibe?
Want spagetti movement? Here’s a trick: create more joints for each body parts. I did it for a mosquito nose. It consists of a few joints connecting small nose parts. Nest them and place their transform-origin
like with a normal character, and suddenly… you’ve got a sausage-shaped nose that bends like it’s made of rubber.
The more elements you add, the more rubbery it will look.
Demo Time
Let’s look at the simple cube characters dancing — powered by proper skeletons and smart nesting.
Takeaways
- Nest your elements by anatomy
- Set
transform-origin
like real joints - Use structure to simplify animation
That’s the skeleton in a nutshell!
Share your demos on your favorite social media and tag me @julia_miocene.
Don’t forget to keep the web weird.