Skip to content
CoDdleCoDoodle home
Food DoodlesAdvancedSVG + CSS

Ramen Shop Bowl

A cozy ramen bowl doodle with layered toppings, rising steam, wiggling noodles, and tiny coordinated animations.

← you, in 45 minutes.

what you'll build

Here's the plan

A cozy ramen bowl scene in SVG — a rounded bowl on a tiny wooden table, warm broth, wavy noodles, a halved egg, a narutomaki swirl, green garnish, chopsticks on the rim, and a cute bowl face. Then four subtle animations run at their own pace so the whole doodle feels alive without chaos.

You’ll learn

  • Layer an SVG scene from back (table, shadow) to front (toppings, chopsticks, face, steam)
  • Build wavy noodles from simple quadratic Bézier paths
  • Group related parts so one keyframe can animate many shapes together
  • Stagger multiple animations with animation-delay so motion feels controlled
Skill level
Advanced
Time
~45 min
Tools
Just a browser
Code type
SVG + CSS
Lines
~95

the steps

Build it, one change at a time

  1. Build the bowl base

    Start with a tiny wooden table and a soft shadow to anchor the scene, then draw the rounded ramen bowl with a rim and a subtle inner curve. Everything else will sit inside or above this bowl.

    <!-- wooden table + shadow -->
    <rect x="24" y="176" width="182" height="14" rx="7" fill="#D9A66C" stroke="#2B3A55" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
    <ellipse cx="115" cy="198" rx="78" ry="8" fill="#2B3A55" opacity="0.15" stroke="none"/>
    
    <!-- rounded ramen bowl -->
    <g class="bowl" fill="#FFF8E7" stroke="#2B3A55" stroke-width="5" stroke-linecap="round" stroke-linejoin="round">
      <path d="M 57 118 L 57 160 Q 57 180 115 180 Q 173 180 173 160 L 173 118 Z"/>
      <ellipse cx="115" cy="118" rx="58" ry="14" fill="none"/>
      <path d="M 65 150 Q 115 158 165 150" fill="none" stroke="#2B3A55" stroke-width="3" opacity="0.10"/>
    </g>
    

    a bowl and table waiting to be filled.

  2. Layer noodles and toppings

    Add a warm broth surface, then wavy noodle paths, a halved egg, a narutomaki swirl, and tiny green onion dots. SVG paint order matters: draw broth first, then noodles, then the toppings that should sit on top.

    <!-- broth surface -->
    <ellipse cx="115" cy="119" rx="52" ry="10" fill="#F5C98C" stroke="#2B3A55" stroke-width="3"/>
    
    <!-- wavy noodles -->
    <g class="noodles" fill="none" stroke="#2B3A55" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round">
      <path d="M 82 119 Q 87 107 94 119 Q 101 131 108 119"/>
      <path d="M 104 121 Q 112 105 120 121 Q 128 137 136 121"/>
      <path d="M 132 119 Q 138 109 145 119 Q 152 129 159 119"/>
    </g>
    
    <!-- halved egg -->
    <g class="egg">
      <ellipse cx="88" cy="115" rx="15" ry="10" fill="#FFFDF7" stroke="#2B3A55" stroke-width="3"/>
      <circle cx="88" cy="115" r="6" fill="#FFD84D" stroke="#2B3A55" stroke-width="2"/>
      <circle cx="86" cy="113" r="1.6" fill="#FFFDF7" stroke="none"/>
    </g>
    
    <!-- narutomaki with coral swirl -->
    <g class="naruto">
      <circle cx="142" cy="116" r="13" fill="#FFFDF7" stroke="#2B3A55" stroke-width="3"/>
      <path d="M 142 116 C 136 110, 148 110, 148 116 C 148 124, 136 124, 136 114 C 136 104, 154 104, 154 118" fill="none" stroke="#FF8FA3" stroke-width="3" stroke-linecap="round"/>
    </g>
    
    <!-- green onion garnish -->
    <g class="garnish" fill="#7DD3A0" stroke="#2B3A55" stroke-width="2">
      <circle cx="116" cy="112" r="2.4"/>
      <circle cx="126" cy="122" r="2"/>
      <circle cx="108" cy="124" r="2.2"/>
      <circle cx="152" cy="112" r="2.3"/>
      <circle cx="136" cy="108" r="1.8"/>
    </g>
    

    the bowl is fully loaded — broth, noodles, egg, narutomaki, and garnish.

  3. Add chopsticks and a tiny face

    Rest two chopsticks on the rim with straight diagonal paths, then give the bowl a cute face with two dot eyes and a small smile. The face turns the bowl from a prop into a character.

    <!-- chopsticks -->
    <g class="chopsticks" fill="none" stroke="#C98A5B" stroke-width="4.5" stroke-linecap="round" stroke-linejoin="round">
      <path d="M 170 110 L 210 80"/>
      <path d="M 178 114 L 218 84"/>
    </g>
    
    <!-- cute bowl face -->
    <g class="face">
      <g class="eye eye-left">
        <circle cx="101" cy="151" r="4.5" fill="#2B3A55" stroke="none"/>
      </g>
      <g class="eye eye-right">
        <circle cx="129" cy="151" r="4.5" fill="#2B3A55" stroke="none"/>
      </g>
      <path d="M 108 161 Q 115 166 122 161" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/>
    </g>
    

    chopsticks on the rim and a little smile — now the bowl has personality.

  4. Animate steam, noodles, and chopsticks

    Add three steam wisps above the bowl, then use keyframes to make them rise and fade, the noodles gently wiggle, the chopsticks tilt, and the bowl face blink. Wrap everything in prefers-reduced-motion so the scene stays calm for viewers who prefer that.

    /* steam wisps above the bowl */
    <g class="steam" fill="none" stroke="#FFFDF7" stroke-width="3" stroke-linecap="round" opacity="0.55">
      <path class="steam-wisp wisp-left" d="M 96 104 Q 91 84 101 74"/>
      <path class="steam-wisp wisp-center" d="M 115 102 Q 115 80 115 70"/>
      <path class="steam-wisp wisp-right" d="M 134 104 Q 139 84 129 74"/>
    </g>
    
    /* animation hooks */
    .ramen-shop-bowl .steam-wisp { opacity: 0; }
    .ramen-shop-bowl .noodles path { transform-origin: 115px 120px; }
    .ramen-shop-bowl .chopsticks { transform-origin: 174px 110px; }
    .ramen-shop-bowl .eye { transform-origin: center; transform-box: fill-box; }
    
    @media (prefers-reduced-motion: no-preference) {
      .ramen-shop-bowl .steam-wisp { animation: ramen-steam 2.8s ease-in-out infinite; }
      .ramen-shop-bowl .noodles path { animation: ramen-noodle-wiggle 2.2s ease-in-out infinite; }
      .ramen-shop-bowl .chopsticks { animation: ramen-chopstick-tilt 3.4s ease-in-out infinite; }
      .ramen-shop-bowl .eye { animation: ramen-blink 4s ease-in-out infinite; }
    }
    
    @keyframes ramen-steam {
      0% { opacity: 0; transform: translateY(0) scale(0.9); }
      20% { opacity: 0.5; }
      80% { opacity: 0.4; }
      100% { opacity: 0; transform: translateY(-22px) scale(1.1); }
    }
    @keyframes ramen-noodle-wiggle {
      0%, 100% { transform: rotate(0deg); }
      50% { transform: rotate(1.6deg); }
    }
    @keyframes ramen-chopstick-tilt {
      0%, 100% { transform: rotate(-2deg); }
      50% { transform: rotate(2deg); }
    }
    @keyframes ramen-blink {
      0%, 90%, 100% { transform: scaleY(1); }
      95% { transform: scaleY(0.1); }
    }
    

    steam rises, noodles wiggle, chopsticks tilt, and the bowl blinks — all at once, gently.

  5. Coordinate multiple animations

    The secret to a busy-but-calm doodle is staggered timing. Each steam wisp, each noodle path, and each motion gets its own duration and delay so nothing syncs up. The result feels organic instead of robotic.

    /* stagger every motion so nothing happens in lockstep */
    .ramen-shop-bowl .wisp-left { animation-delay: 0s; }
    .ramen-shop-bowl .wisp-center { animation-delay: 0.9s; }
    .ramen-shop-bowl .wisp-right { animation-delay: 1.8s; }
    
    .ramen-shop-bowl .noodles path:nth-child(2) { animation-delay: 0.35s; }
    .ramen-shop-bowl .noodles path:nth-child(3) { animation-delay: 0.7s; }
    
    /* different durations keep the loop from feeling like one repeating beat */
    .ramen-shop-bowl .steam-wisp { animation-duration: 2.8s; }
    .ramen-shop-bowl .noodles path { animation-duration: 2.2s; }
    .ramen-shop-bowl .chopsticks { animation-duration: 3.4s; }
    .ramen-shop-bowl .eye { animation-duration: 4s; }
    

    the finished ramen bowl — four motions, four timings, one cozy result.

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="ramen-shop-bowl" viewBox="0 0 230 210" width="230" height="210" role="img" aria-label="Cozy animated ramen bowl doodle">
  <!-- wooden table / base -->
  <rect x="24" y="176" width="182" height="14" rx="7" fill="#D9A66C" stroke="#2B3A55" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
  <!-- soft base shadow -->
  <ellipse cx="115" cy="198" rx="78" ry="8" fill="#2B3A55" opacity="0.15" stroke="none"/>
  <!-- ramen bowl -->
  <g class="bowl" fill="#FFF8E7" stroke="#2B3A55" stroke-width="5" stroke-linecap="round" stroke-linejoin="round">
    <path d="M 57 118 L 57 160 Q 57 180 115 180 Q 173 180 173 160 L 173 118 Z"/>
    <ellipse cx="115" cy="118" rx="58" ry="14" fill="none"/>
    <path d="M 65 150 Q 115 158 165 150" fill="none" stroke="#2B3A55" stroke-width="3" opacity="0.10"/>
  </g>
  <!-- broth and toppings -->
  <g class="broth-toppings">
    <!-- broth surface -->
    <ellipse cx="115" cy="119" rx="52" ry="10" fill="#F5C98C" stroke="#2B3A55" stroke-width="3"/>
    <!-- noodles peeking out -->
    <g class="noodles" fill="none" stroke="#2B3A55" stroke-width="2.8" stroke-linecap="round" stroke-linejoin="round">
      <path d="M 82 119 Q 87 107 94 119 Q 101 131 108 119"/>
      <path d="M 104 121 Q 112 105 120 121 Q 128 137 136 121"/>
      <path d="M 132 119 Q 138 109 145 119 Q 152 129 159 119"/>
    </g>
    <!-- halved egg slice -->
    <g class="egg">
      <ellipse cx="88" cy="115" rx="15" ry="10" fill="#FFFDF7" stroke="#2B3A55" stroke-width="3"/>
      <circle cx="88" cy="115" r="6" fill="#FFD84D" stroke="#2B3A55" stroke-width="2"/>
      <circle cx="86" cy="113" r="1.6" fill="#FFFDF7" stroke="none"/>
    </g>
    <!-- narutomaki with coral swirl -->
    <g class="naruto">
      <circle cx="142" cy="116" r="13" fill="#FFFDF7" stroke="#2B3A55" stroke-width="3"/>
      <path d="M 142 116 C 136 110, 148 110, 148 116 C 148 124, 136 124, 136 114 C 136 104, 154 104, 154 118" fill="none" stroke="#FF8FA3" stroke-width="3" stroke-linecap="round"/>
    </g>
    <!-- tiny green onion garnish dots -->
    <g class="garnish" fill="#7DD3A0" stroke="#2B3A55" stroke-width="2">
      <circle cx="116" cy="112" r="2.4"/>
      <circle cx="126" cy="122" r="2"/>
      <circle cx="108" cy="124" r="2.2"/>
      <circle cx="152" cy="112" r="2.3"/>
      <circle cx="136" cy="108" r="1.8"/>
    </g>
  </g>
  <!-- chopsticks -->
  <g class="chopsticks" fill="none" stroke="#C98A5B" stroke-width="4.5" stroke-linecap="round" stroke-linejoin="round">
    <path d="M 170 110 L 210 80"/>
    <path d="M 178 114 L 218 84"/>
  </g>
  <!-- cute bowl face -->
  <g class="face">
    <g class="eye eye-left">
      <circle cx="101" cy="151" r="4.5" fill="#2B3A55" stroke="none"/>
    </g>
    <g class="eye eye-right">
      <circle cx="129" cy="151" r="4.5" fill="#2B3A55" stroke="none"/>
    </g>
    <path d="M 108 161 Q 115 166 122 161" fill="none" stroke="#2B3A55" stroke-width="3" stroke-linecap="round"/>
  </g>
  <!-- steam wisps -->
  <g class="steam" fill="none" stroke="#FFFDF7" stroke-width="3" stroke-linecap="round" opacity="0.55">
    <path class="steam-wisp wisp-left" d="M 96 104 Q 91 84 101 74"/>
    <path class="steam-wisp wisp-center" d="M 115 102 Q 115 80 115 70"/>
    <path class="steam-wisp wisp-right" d="M 134 104 Q 139 84 129 74"/>
  </g>
</svg>
Open in Playground

tips & gotchas

Mistakes we actually made

If the bowl looks like it's floating, add a soft ellipse shadow underneath — it's the cheapest way to ground an SVG object.

SVG paints in document order, same as HTML. Draw the table and bowl first, then broth, noodles, toppings, chopsticks, face, and steam last so steam rises over everything.

transform-origin on SVG paths needs SVG coordinate-space values, not CSS pixels. For the noodles, 115px 120px is the center of the bowl in the viewBox.

A blink that lasts 4s but only squashes for 5% of the loop feels natural because the eyes are open almost the whole time.

Use prefers-reduced-motion: no-preference so viewers who choose reduced motion get a still, readable illustration.

make it yours

Remix it

  • Broth coloreasy

    Swap #F5C98C for a miso tan, a spicy red, or a creamy tonkotsu white.

  • Extra toppingeasy

    Add a slice of chashu pork or a few corn kernels as small SVG shapes.

  • Bigger steammedium

    Lengthen the steam paths and add one more wisp with a longer delay.

  • Chopstick tapmedium

    Animate the chopsticks with a tiny up-and-down motion like they're tapping the rim.

challenge extension

Same layered approach, new food mascot: build a boba tea cup with a face, then animate the boba pearls bobbing and the straw wiggling independently.