Draw and Animate Bender's Face with CSS

January 23, 2020

Futurama’s lively characters and simple animation can easily be recreated with CSS using basic shapes. Bender, specifically, is drawn almost completely with basic shapes. This tutorial will demonstrate how to create Bender’s face with CSS and animate his eyelids to make it seem like he’s squinting. Check out the completed project on Codepen.

Container and Color

First, let’s create a container and define the background. The hex color #a6b4c4 matches Bender’s metal color pretty well, but we can give the illusion (sort of) of shininess by creating a radial gradient with the hex color #59798e.

Bender Container

<div class="Bender"></div>
body {
  overflow: hidden;
  padding: 0;
  margin: 0;
}
.Bender {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  background: #a6b4c4;
  background-image: radial-gradient(#a6b4c4, #59798e);
}

Eyes

Drawing with CSS is a lot easier when we can break images down into simple shapes that are easily created with CSS. Bender’s eyes, for example, can be broken into three basic shapes: ellipses, circles, and squares.

Bender Eye Breakdown

The outer rim is composed of the space between the Beneder_eyes border and the Bender__socket element. The eye elements, Bender_eye, have a larger height than the Bender_socket element so that we can clip the top and bottom parts of the eye to create the illusion that the eyes are nested inside the socket. Add the following HTML elements and CSS to create the eyes.

Bender Eyes

<div class="Bender">
  <div class="Bender__eyes">
    <div class="Bender__socket">
      <div class="Bender__eye">
        <div class="Bender__pupil"></div>
      </div>
      <div class="Bender__eye">
        <div class="Bender__pupil"></div>
      </div>
    </div>
  </div>
</div>
.Bender__eyes {
  width: 400px;
  height: 150px;
  border: 3px solid black;
  border-radius: 200px;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
}

.Bender__socket {
  width: 375px;
  height: 125px;
  border: 3px solid black;
  border-radius: 200px;
  background: black;
  display: flex;
  justify-content: center;
  overflow: hidden;
}

.Bender__eye {
  height: 145px;
  width: 145px;
  background: #fefbb8;
  border-radius: 100%;
  margin: -10px 10px 0px 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
}
.Bender__pupil {
  width: 20px;
  height: 20px;
  background: black;
}

Mouth

Bender’s mouth is essentially an ellipse with two horizontal lines and few vertical lines. We can space seven, 4px width, vertical lines across the Bender__mouth ellipse using flexbox and justify-content: space-around. The two horizontal lines are a little more difficult to place since they’re not evenly spaced from the top or middle. But we can use absolute position and the calc() function to place them exactly where we want.

Bender Eyes

<div class="Bender">
  ...
  <div class="Bender__mouth">
    <div class="Bender__tooth"></div>
    <div class="Bender__tooth"></div>
    <div class="Bender__tooth"></div>
    <div class="Bender__tooth"></div>
    <div class="Bender__tooth"></div>
    <div class="Bender__tooth"></div>
    <div class="Bender__tooth"></div>

    <div class="Bender__lip"></div>
    <div class="Bender__lip"></div>
  </div>
</div>
.Bender__mouth {
  width: 275px;
  height: 100px;
  background: #fefbb8;
  margin-top: 80px;
  border-radius: 50px;
  border: 4px solid black;
  display: flex;
  align-items: center;
  justify-content: space-around;
  overflow: hidden;
  position: relative;
}
.Bender__tooth {
  height: 100px;
  width: 4px;
  background: black;
}
.Bender__lip {
  position: absolute;
  width: 275px;
  height: 4px;
  background: black;
  top: calc(33% - 2px);
}
.Bender__lip:last-of-type {
  top: calc(66% - 2px);
}

Animate the Eyes

We can animate Bender squinting his eyes, like he’s skeptical or angry, by animating eyelids up and down over his eyes. We could create separate components for his eyelids, but in this case, we will use the ::before and ::after pseudo elements to create the top and bottom eyelid respectively. Using position: absolute, set the eyelids directly above the eyes as shown in the image below.

Bender Eyelids

These will be hidden, however, by the Bender__socket element which has overflow: hidden.

.Bender__eye::before {
  content: "";
  position: absolute;
  width: 145px;
  height: 50px;
  top: -50px;
  background: black;
}
.Bender__eye::after {
  content: "";
  position: absolute;
  width: 145px;
  height: 50px;
  bottom: -50px;
  background: black;
}

The goal is to animate the top eyelid down and bottom eyelid up to give the illusion that the eyelids are closing over the eye. We can do this by adding a transform that translates the eyelids along the Y axis, for example transform: translateY(-50px). Since we defined the top eyelid to be -50px above the eye, we need to start at that position, translateY(0px), and animate back down to the near the pupil, translateY(50px). The bottom eyelid needs to go in the opposite direction translateY(-50px). Define two @keyframes that go from 0% to 100% for both the top and bottom eyelids.

@keyframes topEyelid {
  0% {
    transform: translateY(0px);
  }
  100% {
    transform: translateY(50px);
  }
}
@keyframes bottomEyelid {
  0% {
    transform: translateY(0px);
  }
  100% {
    transform: translateY(-50px);
  }
}

Next, add the animation property to each eyelid with the appropriate keyframe name at the end.

.Bender__eye::before {
  animation: 5s ease-in-out 1s infinite topEyelid;
}
.Bender__eye::after {
  animation: 5s ease-in-out 1s infinite bottomEyelid;
}

Bender Eyelid animation

One problem with this animation is that it ends abruptly and resets the eyelids to their initial positions instead of animating them back. We can make this animation more natural by breaking the animation keyframes into more parts.

First, we get to the end animation more quickly by animating from 0% to 20%. Then we can hold that position by defining the same transform until 80%. Finally, we can return to the starting position at 100%. This means that the start of the animation 0% and the end 100% are at the same spot so the eyelid will animate away from the starting position and animate back to the starting position.

@keyframes topEyelid {
  0% {
    transform: translateY(0);
  }
  20% {
    transform: translateY(50px);
  }
  80% {
    transform: translateY(50px);
  }
  100% {
    transform: translateY(0px);
  }
}

@keyframes bottomEyelid {
  0% {
    transform: translateY(0px);
  }
  20% {
    transform: translateY(-50px);
  }
  80% {
    transform: translateY(-50px);
  }
  100% {
    transform: translateY(0px);
  }
}

Bender Gif

Now we have a much more natural animation.

Conclusion

There are probably half a dozen different ways to create Bender with CSS, but I hope this version helps you see how easy drawing with CSS can be.