Crybaby
A chibi Crybaby sticker with a wavy pink bob, huge glossy eyes brimming with tears, and one brave teardrop that rolls down its cheek on loop — sweet-sad in the most healing way.
This coded drawing is a fan-art practice example created for educational purposes only. CRYBABY is a copyrighted character produced under license by POP MART. CoDoodle is not affiliated with, endorsed by, or sponsored by POP MART.
← you, in 35 minutes.
what you'll build
Here's the plan
A chibi Crybaby sticker — wavy pink bob, huge glossy eyes brimming with tears, blush, and a tiny wobbly pout — swaying gently on warm cream paper while one brave teardrop slides down its cheek, fades away, and wells up again. The tear lives in its OWN group, so the whole crying loop is one small keyframe block.
You’ll learn
- Layering a glossy eye: a dark base circle, a tear-pool crescent hugging the bottom edge, and white highlight dots on top
- Drawing back-to-front: hair first, then body, with the head last so it overlaps both
- Looping a one-way animation (a tear sliding down) without a visible snap-back, using opacity fades at both ends
- Anchoring transforms believably — a feet-level origin for the sway, transform-box: fill-box for blinks and twinkles
- Skill level
- Intermediate
- Time
- ~35 min
- Tools
- Just a browser
- Code type
- SVG + CSS
- Lines
- ~65
the steps
Build it, one change at a time
Set the stage
Warm paper, one soft ground shadow where Crybaby will stand, and a scatter of floating teardrops and sparkles. The shadow stays OUTSIDE the character group so it can squeeze on its own beat, and every prop shares a cb-prop class so they're ready to twinkle later.
<rect x="0" y="0" width="200" height="200" rx="18" fill="#FBF2E5" stroke="none"/> <ellipse class="cb-shadow" cx="100" cy="176" rx="42" ry="9" fill="#2B3A55" opacity="0.16" stroke="none"/> <!-- floating teardrops set the mood before the character even shows up --> <path class="cb-prop cb-drop1" d="M34 58 C31 63 29.5 66.5 31 70 C32.5 73.5 38.5 73.5 40 70 C41.5 66.5 37 63 34 58 Z" fill="#BFD9F2" stroke="#2B3A55" stroke-width="2.4" stroke-linejoin="round"/> <path class="cb-prop cb-drop2" d="M167 116 C164.5 120 163.5 123 164.8 125.8 C166 128.5 171 128.5 172.2 125.8 C173.5 123 169.5 120 167 116 Z" fill="#BFD9F2" stroke="none"/> <path class="cb-prop cb-spark1" d="M164 50 L168 58 L164 66 L160 58 Z" fill="#FFD84D" stroke="#2B3A55" stroke-width="2" stroke-linejoin="round"/> <path class="cb-prop cb-spark2" d="M40 126 L43 132 L40 138 L37 132 Z" fill="#FF6B5E" stroke="none"/>an empty stage: one soft shadow, two teardrops, two sparkles.
Build the soft silhouette
Paint order does the emotional heavy lifting: the wavy bob goes down FIRST (it's the furthest back), then the small cream body with stub arms and feet, then the big pale head LAST so it overlaps the hair's inner edge and the body's shoulders. Everything lives inside one cb-all group so the whole character can sway together.
<g class="cb-all"> <!-- hair first: one wavy blob that the head will overlap --> <path class="cb-hair" d="M100 40 C77 40 59 53 53 74 C48 90 50 106 56 118 C58 124 66 125 68 118 C70 112 75 112 77 118 C79 124 87 124 88 117 C88 108 90 100 100 100 C110 100 112 108 112 117 C113 124 121 124 123 118 C125 112 130 112 132 118 C134 125 142 124 144 118 C150 106 152 90 147 74 C141 53 123 40 100 40 Z" fill="#FF8FA3" stroke="#2B3A55" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> <g class="cb-body" stroke="#2B3A55" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"> <path d="M74 136 C65 139 60 148 65 155 C69 161 79 158 80 148 Z" fill="#FFFDF7"/> <path d="M126 136 C135 139 140 148 135 155 C131 161 121 158 120 148 Z" fill="#FFFDF7"/> <ellipse cx="100" cy="148" rx="29" ry="26" fill="#FFFDF7"/> <path d="M86 168 C77 170 73 177 78 181 C83 185 95 182 96 173 Z" fill="#FFFDF7"/> <path d="M114 168 C123 170 127 177 122 181 C117 185 105 182 104 173 Z" fill="#FFFDF7"/> </g> <!-- head goes last so it overlaps the hair and the shoulders --> <path class="cb-head" d="M100 55 C126 55 142 72 141 95 C140 118 123 133 100 133 C77 133 60 118 59 95 C58 72 74 55 100 55 Z" fill="#F6E7EF" stroke="#2B3A55" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/> </g>a faceless little softie — wavy bob, round head, small body.
Fill the eyes with tears
Each eye is a little stack: a big navy circle, a tear-blue crescent hugging its bottom edge (that's the tears welling up), then white highlight dots for the gloss. Add worried brows, blush, a tiny wobbly pout — and the star of the show: one teardrop on the left cheek, in its OWN cb-tear group so it can slide later.
<!-- two wispy fringe strands so the bob reads as hair, not a helmet --> <g class="cb-fringe" fill="none" stroke="#FF8FA3" stroke-width="3.5" stroke-linecap="round"> <path d="M88 57 C91 63 89 68 84 71"/> <path d="M104 56 C107 62 105 67 100 70"/> </g> <g class="cb-face"> <path d="M69 79 C74 75.5 81 74.5 87 75.5" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/> <path d="M113 75.5 C119 74.5 126 75.5 131 79" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/> <g class="cb-eye cb-eye-l"> <circle cx="81" cy="95" r="13.5" fill="#2B3A55" stroke="#2B3A55" stroke-width="2"/> <!-- the tear pool: a crescent that hugs the bottom of the eye --> <path d="M68 98.5 C69.8 105.5 74.8 108.6 81 108.6 C87.2 108.6 92.2 105.5 94 98.5 C89.5 103 72.5 103 68 98.5 Z" fill="#BFD9F2" stroke="none"/> <circle cx="76" cy="89.5" r="4.6" fill="#FFFDF7" stroke="none"/> <circle cx="86.5" cy="99" r="2" fill="#FFFDF7" stroke="none" opacity="0.9"/> <circle cx="75" cy="103.5" r="1.3" fill="#FFFDF7" stroke="none" opacity="0.85"/> </g> <g class="cb-eye cb-eye-r"> <circle cx="119" cy="95" r="13.5" fill="#2B3A55" stroke="#2B3A55" stroke-width="2"/> <path d="M106 98.5 C107.8 105.5 112.8 108.6 119 108.6 C125.2 108.6 130.2 105.5 132 98.5 C127.5 103 110.5 103 106 98.5 Z" fill="#BFD9F2" stroke="none"/> <circle cx="114" cy="89.5" r="4.6" fill="#FFFDF7" stroke="none"/> <circle cx="124.5" cy="99" r="2" fill="#FFFDF7" stroke="none" opacity="0.9"/> <circle cx="113" cy="103.5" r="1.3" fill="#FFFDF7" stroke="none" opacity="0.85"/> </g> <ellipse cx="68" cy="110" rx="4.8" ry="3.5" fill="#FF8FA3" stroke="none" opacity="0.7"/> <ellipse cx="132" cy="110" rx="4.8" ry="3.5" fill="#FF8FA3" stroke="none" opacity="0.7"/> <!-- the pout: a tiny "w" wobble instead of a plain frown --> <path d="M93 120 C96 116 98.5 116 100 118.8 C101.5 116 104 116 107 120" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/> <!-- the cheek tear gets its OWN group so it can slide on its own --> <g class="cb-tear"> <path d="M74 110 C71.5 114.8 70 118.2 71.4 121.4 C72.9 124.7 78.5 124.7 80 121.4 C81.4 118.2 76.8 114.8 74 110 Z" fill="#BFD9F2" stroke="#2B3A55" stroke-width="2.5" stroke-linejoin="round"/> <circle cx="73.5" cy="119" r="1.4" fill="#FFFDF7" stroke="none"/> </g> </g>the finished static Crybaby, eyes full and pout wobbling.
Sway, blink, let one tear go
The whole cb-all group rocks gently from between its feet while the shadow squeezes underneath. The tear loop is the trick: it fades IN near the top of the cheek, slides down 13px, and fades OUT before the loop restarts — the invisible frames at both ends hide the jump back to the start. Eyes blink slowly with transform-box: fill-box origins, props float and twinkle staggered, and all of it sits inside @media (prefers-reduced-motion: no-preference) so it stills politely when motion isn't wanted.
@media (prefers-reduced-motion: no-preference) { .cb .cb-all { transform-origin: 100px 174px; animation: cb-sway 3.6s ease-in-out infinite; } .cb .cb-shadow { transform-box: fill-box; transform-origin: center; animation: cb-shadow 3.6s ease-in-out infinite; } .cb .cb-eye { transform-box: fill-box; transform-origin: center; animation: cb-blink 5.6s ease-in-out infinite; } .cb .cb-tear { animation: cb-tear-fall 3.6s ease-in infinite; } .cb .cb-prop { transform-box: fill-box; transform-origin: center; } .cb .cb-drop1 { animation: cb-float 4.4s ease-in-out infinite; } .cb .cb-drop2 { animation: cb-float 4.4s ease-in-out -2.2s infinite; } .cb .cb-spark1 { animation: cb-twinkle 2.8s ease-in-out infinite; } .cb .cb-spark2 { animation: cb-twinkle 2.8s ease-in-out 1.1s infinite; } } @keyframes cb-sway { 0%, 100% { transform: rotate(-1.4deg) scale(1.01, 0.99); } 50% { transform: rotate(1.4deg) scale(0.99, 1.01); } } @keyframes cb-shadow { 0%, 100% { transform: scaleX(1); opacity: 0.16; } 50% { transform: scaleX(0.92); opacity: 0.12; } } @keyframes cb-blink { 0%, 52%, 58%, 100% { transform: scaleY(1); } 55% { transform: scaleY(0.08); } } /* invisible at 0% AND 100% — the fade hides the loop's snap-back */ @keyframes cb-tear-fall { 0%, 10% { transform: translateY(-2px); opacity: 0; } 24% { transform: translateY(0); opacity: 1; } 66% { transform: translateY(7px); opacity: 1; } 100% { transform: translateY(13px); opacity: 0; } } @keyframes cb-float { 0%, 100% { transform: translateY(0); opacity: 0.55; } 50% { transform: translateY(-5px); opacity: 1; } } @keyframes cb-twinkle { 0%, 100% { opacity: 0.35; transform: scale(0.82); } 45% { opacity: 1; transform: scale(1.14); } }swaying, blinking, quietly crying on loop — zero JavaScript.
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.
<svg class="cb" viewBox="0 0 200 200" width="200" height="200" role="img" aria-label="A chibi Crybaby fan-art doodle swaying gently while it blinks, a teardrop slides down its cheek, and sparkles twinkle">
<rect x="0" y="0" width="200" height="200" rx="18" fill="#FBF2E5" stroke="none"/>
<ellipse class="cb-shadow" cx="100" cy="176" rx="42" ry="9" fill="#2B3A55" opacity="0.16" stroke="none"/>
<path class="cb-prop cb-drop1" d="M34 58 C31 63 29.5 66.5 31 70 C32.5 73.5 38.5 73.5 40 70 C41.5 66.5 37 63 34 58 Z" fill="#BFD9F2" stroke="#2B3A55" stroke-width="2.4" stroke-linejoin="round"/>
<path class="cb-prop cb-drop2" d="M167 116 C164.5 120 163.5 123 164.8 125.8 C166 128.5 171 128.5 172.2 125.8 C173.5 123 169.5 120 167 116 Z" fill="#BFD9F2" stroke="none"/>
<path class="cb-prop cb-spark1" d="M164 50 L168 58 L164 66 L160 58 Z" fill="#FFD84D" stroke="#2B3A55" stroke-width="2" stroke-linejoin="round"/>
<path class="cb-prop cb-spark2" d="M40 126 L43 132 L40 138 L37 132 Z" fill="#FF6B5E" stroke="none"/>
<g class="cb-all">
<path class="cb-hair" d="M100 40 C77 40 59 53 53 74 C48 90 50 106 56 118 C58 124 66 125 68 118 C70 112 75 112 77 118 C79 124 87 124 88 117 C88 108 90 100 100 100 C110 100 112 108 112 117 C113 124 121 124 123 118 C125 112 130 112 132 118 C134 125 142 124 144 118 C150 106 152 90 147 74 C141 53 123 40 100 40 Z" fill="#FF8FA3" stroke="#2B3A55" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<g class="cb-body" stroke="#2B3A55" stroke-width="4" stroke-linecap="round" stroke-linejoin="round">
<path d="M74 136 C65 139 60 148 65 155 C69 161 79 158 80 148 Z" fill="#FFFDF7"/>
<path d="M126 136 C135 139 140 148 135 155 C131 161 121 158 120 148 Z" fill="#FFFDF7"/>
<ellipse cx="100" cy="148" rx="29" ry="26" fill="#FFFDF7"/>
<path d="M86 168 C77 170 73 177 78 181 C83 185 95 182 96 173 Z" fill="#FFFDF7"/>
<path d="M114 168 C123 170 127 177 122 181 C117 185 105 182 104 173 Z" fill="#FFFDF7"/>
</g>
<path class="cb-head" d="M100 55 C126 55 142 72 141 95 C140 118 123 133 100 133 C77 133 60 118 59 95 C58 72 74 55 100 55 Z" fill="#F6E7EF" stroke="#2B3A55" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
<g class="cb-fringe" fill="none" stroke="#FF8FA3" stroke-width="3.5" stroke-linecap="round">
<path d="M88 57 C91 63 89 68 84 71"/>
<path d="M104 56 C107 62 105 67 100 70"/>
</g>
<g class="cb-face">
<path d="M69 79 C74 75.5 81 74.5 87 75.5" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/>
<path d="M113 75.5 C119 74.5 126 75.5 131 79" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/>
<g class="cb-eye cb-eye-l">
<circle cx="81" cy="95" r="13.5" fill="#2B3A55" stroke="#2B3A55" stroke-width="2"/>
<path d="M68 98.5 C69.8 105.5 74.8 108.6 81 108.6 C87.2 108.6 92.2 105.5 94 98.5 C89.5 103 72.5 103 68 98.5 Z" fill="#BFD9F2" stroke="none"/>
<circle cx="76" cy="89.5" r="4.6" fill="#FFFDF7" stroke="none"/>
<circle cx="86.5" cy="99" r="2" fill="#FFFDF7" stroke="none" opacity="0.9"/>
<circle cx="75" cy="103.5" r="1.3" fill="#FFFDF7" stroke="none" opacity="0.85"/>
</g>
<g class="cb-eye cb-eye-r">
<circle cx="119" cy="95" r="13.5" fill="#2B3A55" stroke="#2B3A55" stroke-width="2"/>
<path d="M106 98.5 C107.8 105.5 112.8 108.6 119 108.6 C125.2 108.6 130.2 105.5 132 98.5 C127.5 103 110.5 103 106 98.5 Z" fill="#BFD9F2" stroke="none"/>
<circle cx="114" cy="89.5" r="4.6" fill="#FFFDF7" stroke="none"/>
<circle cx="124.5" cy="99" r="2" fill="#FFFDF7" stroke="none" opacity="0.9"/>
<circle cx="113" cy="103.5" r="1.3" fill="#FFFDF7" stroke="none" opacity="0.85"/>
</g>
<ellipse cx="68" cy="110" rx="4.8" ry="3.5" fill="#FF8FA3" stroke="none" opacity="0.7"/>
<ellipse cx="132" cy="110" rx="4.8" ry="3.5" fill="#FF8FA3" stroke="none" opacity="0.7"/>
<path d="M93 120 C96 116 98.5 116 100 118.8 C101.5 116 104 116 107 120" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/>
<g class="cb-tear">
<path d="M74 110 C71.5 114.8 70 118.2 71.4 121.4 C72.9 124.7 78.5 124.7 80 121.4 C81.4 118.2 76.8 114.8 74 110 Z" fill="#BFD9F2" stroke="#2B3A55" stroke-width="2.5" stroke-linejoin="round"/>
<circle cx="73.5" cy="119" r="1.4" fill="#FFFDF7" stroke="none"/>
</g>
</g>
</g>
</svg>
tips & gotchas
Mistakes we actually made
My first tear pool was a straight horizontal line across each eye — it looked like a loading bar. Curve the pool's top edge so the blue reads as liquid clinging to the bottom of the eye, not a progress meter.
A tear that slides down and snaps back to the top reads as a glitch. Fade it out at the END of the loop and fade it in at the START — the few invisible frames on both sides completely hide the teleport.
I first anchored the sway at the head and Crybaby swept the floor like a windshield wiper. Pivot the whole character from between its feet (100px 174px) so it rocks like a standing plush.
Keep the sadness slow: a 3.6s sway and one blink every 5.6s. When I sped everything up 'for energy', the crying stopped reading as feelings and started reading as panic.
make it yours
Remix it
- Happy tearseasy
Flip the pout into a tiny smile and tilt the brows the other way — same tears, but now they're the overwhelmed-with-joy kind.
- New hair coloureasy
Recolour the bob — try tear-blue (#BFD9F2) or sunshine (#FFD84D), keeping the navy outline so it stays a sticker.
- Gentle raineasy
Duplicate the floating teardrop props a few times and give each a slow falling translateY loop with staggered delays.
- Double the feelingsmedium
Add a second cb-tear group on the right cheek and start its animation half a cycle late (animation-delay: -1.8s) so the tears alternate.
challenge extension
Give the tear somewhere to land: add a tiny tear-blue puddle ellipse under the chin that scales up from nothing and fades away on the SAME 3.6s clock as the tear — timed so it blooms at exactly the moment the falling drop disappears.