Skip to content
CoDdleCoDoodle home
Original CharactersBeginnerHTML + CSS

Blink Bean

A tiny bean-shaped CSS character that blinks with one gentle keyframe animation.

← a soft little friend who blinks at you.

what you'll build

Here's the plan

A tiny original CoDoodle character — a soft bean with a sprout, a smiling face, and a gentle blink, built from pure divs and CSS (no SVG, no images).

You’ll learn

  • Shaping a bean with an eight-value border-radius
  • Stacking a face out of simple absolute-positioned shapes
  • Holding a CSS blink open most of the loop for a natural flicker
Skill level
Beginner
Time
~15 min
Tools
Just a browser
Code type
HTML + CSS
Lines
~42

the steps

Build it, one change at a time

  1. Shape the bean

    A plain box bulges into a bean when you round the top more than the bottom — the eight-value border-radius curves the silhouette. A soft oval underneath becomes the ground shadow.

    .bean-wrap { position: relative; width: 200px; height: 180px; }
    .shadow { position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%);
      width: 110px; height: 15px; background: #2B3A55; border-radius: 50%; opacity: 0.12; }
    .bean { position: absolute; left: 50%; top: 18px; transform: translateX(-50%);
      width: 140px; height: 135px; background: #FFFDF7; border: 6px solid #2B3A55;
      border-radius: 50% 50% 46% 46% / 58% 58% 42% 42%; }
    

    it's a bean, sort of.

  2. Give it a face

    Two ink dots for eyes, coral blush, and a bottom-only border arc for a smile. Each piece is absolutely placed inside the bean.

    .eye { position: absolute; top: 46px; width: 14px; height: 18px; background: #2B3A55; border-radius: 50%; }
    .eye-left { left: 40px; } .eye-right { right: 40px; }
    .blush { position: absolute; top: 70px; width: 16px; height: 10px; background: #FFB3AD; border-radius: 50%; opacity: 0.85; }
    .smile { position: absolute; top: 74px; left: 50%; transform: translateX(-50%);
      width: 28px; height: 14px; border: 3px solid #2B3A55; border-top: none; border-radius: 0 0 28px 28px; }
    

    now it's looking at you.

  3. Add arms, a sprout & a tiny scene

    Little side arms, a mint sprout on top, a grass tuft, and a sparkle made from two pseudo-elements crossing into a plus.

    .arm { position: absolute; top: 74px; width: 14px; height: 22px; background: #FFFDF7; border: 5px solid #2B3A55; border-radius: 50%; }
    .sprout { position: absolute; top: -16px; left: 50%; transform: translateX(-50%);
      width: 8px; height: 16px; background: #5ECBB4; border: 4px solid #2B3A55; border-radius: 50% 50% 6px 6px; }
    .sparkle::before, .sparkle::after { content: ""; position: absolute; background: #FFD84D; border-radius: 2px; }
    

    a whole tiny scene.

  4. Make it blink & breathe

    A blink keyframe holds the eyes open almost the whole loop, then squashes them for a flicker. A subtle breathe bobs the whole bean — keeping translateX(-50%) inside the keyframe so it stays centered while it bobs.

    .eye { transform-origin: center; animation: bean-blink 4s ease-in-out infinite; }
    .bean { animation: bean-breathe 3.4s ease-in-out infinite; }
    @keyframes bean-blink { 0%, 90%, 100% { transform: scaleY(1); } 95% { transform: scaleY(0.08); } }
    @keyframes bean-breathe { 0%, 100% { transform: translateX(-50%) translateY(0) rotate(0deg); }
      50% { transform: translateX(-50%) translateY(-3px) rotate(-1.5deg); } }
    

    it's alive — and it blinks at you.

the complete code

Everything, in one place

Skipped straight to the end? Welcome. Copy the whole thing, download it, or open it in the Playground to start remixing.

<div class="bean-wrap">
  <div class="shadow"></div>
  <div class="bean">
    <div class="eye eye-left"></div>
    <div class="eye eye-right"></div>
    <div class="blush blush-left"></div>
    <div class="blush blush-right"></div>
    <div class="smile"></div>
    <div class="arm arm-left"></div>
    <div class="arm arm-right"></div>
    <div class="sprout"></div>
  </div>
  <div class="grass"></div>
  <div class="sparkle"></div>
</div>
Open in Playground

tips & gotchas

Mistakes we actually made

If the bean looks like an egg, your border-radius top values are too even — round them more.

Hold the blink open for ~90% of the loop; a 50/50 blink reads as a twitch, not a blink.

Keep translateX(-50%) inside the breathe keyframe or the bean drifts off-center while it bobs.

make it yours

Remix it

  • Sleepy beaneasy

    Slow the blink to 6s and add a tiny 'z' sparkle.

  • Bean gangmedium

    Reuse the bean at three sizes and stagger the blinks so they never sync.

challenge extension

Give the bean a second expression — a surprised 'o' mouth that pops in for one frame right after each blink.