Animating your mascot! Case study: “Jeff the PHP Butler”

I created an animated version of phpbot.org’s mascot using only HTML and CSS. Wanna know how I did it?

An animated GIF of the end result!

View the completed animation

WHAT IS A MASCOT?

A mascot is an illustrated character that represents a company. Mascots can act as an ambassador for a business. Famous mascots include the Kool-Aid Man. Oh yeahhhhh!

WHAT IS A PHP BUTLER?

Writing out PHP code line-by-line is no longer necessary when you have a free personal PHP butler do it for you! Visit phpbot.org to give the tool a try.

Rhys Adams is the developer behind phpbot.org and the creator of “Jeff”. When I saw Rhys’ illustration of the PHP Butler, I saw a design that was begging to be recreated using code!

WHY CODE?

Why?! How dare you! Creating this character is going to be awesome because…

  • Code is lightweight and will load more quickly than most images.
  • CSS animation is mobile-friendly.
  • A character created using code will render beautifully regardless of viewport. Bring on the retina display!
  • There is great browser support for CSS animation.

The Process

Enough of the chit chat — Let’s make something cool!

MEASUREMENTS & COLOR SAMPLING

First, let’s take Jeff’s measurements. Although I plan to take some small liberties with the design, I want to be true to Rhys' vision.

I can also sample the colors and match up the hex exactly.

Pixel measurements
The color palette

THE MARKUP

The HTML needed is minimal. We’ll do the heavy lifting in the style sheet because that approach will give us the most control when we’re animating.

<div class=”php-bot”>
 <span class=”hat”></span>
 <span class=”eye”></span>
 <span class=”mouth”></span>
</div>

THE STYLES

Dudes, I am salivating just thinking about this code!

The body: We can begin by creating a 300px circle and centering it in the middle of the screen. This can be tricky! If you have ever struggled with centering content, you will love Chris Coyiers’ Centering in CSS: A Complete Guide.

The eye: Using a similar approach to the body, we’ll create a centered circle to mimic a pupil. This time, we’ll add a border to create the white of Jeff’s eye.

.php-bot .eye {
 width: 52px;
 height: 52px;
 background-color: #444;
 display: block;
 margin: 47px auto 0px auto;
 border-radius: 50%;
 border: 46px solid #fff;
 position: relative;
}

The mouth and tongue: Adding border-radius to the lower-right and lower-left corners of this shape create the smile. Don’t forget to set the overflow to hidden. Gotta keep Jeff’s tongue inside his mouth.

Speaking of Jeff’s tongue; I used a well-placed pseudo element to create it!

.php-bot .mouth {
 width: 100px;
 height: 50px;
 background-color: #444;
 display: block;
 margin: 25px auto 0px auto;
 border-bottom-right-radius: 50px;
 border-bottom-left-radius: 50px;
 overflow: hidden;
}
/* PSEUDO ELEMENT */
.php-bot .mouth:before {
 content: ‘’;
 width: 60px;
 height: 60px;
 background-color: #ff7c7c;
 display: block;
 border-radius: 50%;
 margin: 30px auto 0px auto;
}

The hat: Absolute positioning and a negative top placement help place the hat atop Jeff’s head.

.php-bot .hat {
 width: 60px;
 height: 18px;
 position: absolute;
 top: -18px;
 left: 50%;
 margin-left: -30px;
 background-color: #b3b3b3;
}

Additional pseudo elements help to form the top of the hat and the brim.

.php-bot .hat:before {
 content: ‘’;
 height: 46px;
 width: 60px;
 background-color: #444;
 border-top-right-radius: 50px;
 border-top-left-radius: 50px;
 position: absolute;
 top: -46px;
}
.php-bot .hat:after {
 content: ‘’;
 border-bottom: 5px solid #444;
 border-right: 3px solid #444;
 border-left: 3px solid #444;
 width: 92px;
 height: 10px;
 display: block;
 border-bottom-right-radius: 30px;
 border-bottom-left-radius: 30px;
 left: -19px;
 bottom: -5px;
 position: absolute;
}

The shadow: By now, you’ve probably realized that I really like pseudo elements. Maybe I’m overusing them? The shadow is a pseudo element placed beneath Jeff.

.php-bot:before {
 content: ‘’;
 width: 200px;
 height: 30px;
 background-color: #e1e1e1;
 position: absolute;
 border-radius: 50%;
 top: 95%;
 left: 50%;
 margin-left: -100px;
}

THE ANIMATION

This part of the process is the most difficult to communicate. Although I can share the code, one should also consider the principles of animation.

Since Jeff’s body is literally comprised of a circle, we can easily utilize the squash and stretch principle to make him look as though he’s leaping.

“Squash and Stretch refers to the volume of the character and the shapes it forms through movement. For example a character bends down to jump and then leaps into the air.
The ‘squash and stretch’ principle illustrated.
This can be seen as squash and stretch. When the character is knelt down they form a more squashed shape, when they leap up into the air they form a stretched shape.
This same principle can be applied to anything. For example a bouncing ball.”¹

Learn more about the 12 basic principles of animation!

With the addition of these animation styles…

.php-bot {
 animation-name: jump;
 animation-duration: 2s;
 animation-iteration-count: infinite;
}

… and these keyframes…

@keyframes jump {
 0%, 20% {
 margin: -150px 0px 0px -150px;
 height: 300px;
 width: 300px;
}
 40%, 70% {
 margin: -100px 0px 0px -175px;
 height: 250px;
 width: 350px;
}
 60% {
 margin: -300px 0px 0px -125px;
 height: 350px;
 width: 250px;
}
 80% {
 margin: -50px 0px 0px -200px;
 height: 200px;
 width: 400px;
}
 100% {
 margin: -150px 0px 0px -150px;
 height: 300px;
 width: 300px;
}
}

Jeff begins to leap! But, his mouth falls off of his body and his shadow leaps up into the air with him! To make this look more natural, we still have to consider the secondary action and the timing of this animation.

Jeff leaps!

I think it would be a bit exhausting to examine each keyframe, so let’s quickly summarize…

  • The shadow: The shadow is a pseudo element of Jeff’s body. Therefore it’s following him into the air. We can make the shadow look more natural by pushing it away from Jeff as he moves upward.
  • The eye: Reducing the height (using borders) of the eye gives the impression of Jeff’s body rolling backwards.
Pop!
  • The hat: We can have some fun by popping Jeff’s hat right off his head at the peak of his jump! The hat can land on the top of his head as he returns towards the ground. This is a good example of the principle of secondary action.
  • The mouth: I chose to morph Jeff’s mouth into a circle to give the impression that he’s huffing and puffing as he forces his bulbous body skyward. I added some cheeks to really hammer this home.
Once again, a look at the final product.

If you have any questions, find me on Twitter! You can check out the completed animation on my website!