Skip to content
animorio
IT
All components

The egg timer

Timers, Physics, TransitionsCanvas, GSAPAdvancedCompressed weight: Demo 15 KBGSAP 28 KBFreeDownload the zip

The egg timer of a cooking app, with the egg cut in half really cooking as the time runs down: the heat of the water moves in through the shell as in real physics, the white turns white from the edge inwards and the yolk sets from its own edge. Soft, jammy or hard come out by themselves. When the time is up the egg is lifted out of the water with a little jump and the yolk wobbles as much as it is still runny.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The egg timer</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/rubik@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the egg timer: the egg is drawn cut in half, and while the time runs down it cooks from the shell inwards,
         worked out as heat that really moves through the white and into the yolk. When the time is up the egg is
         lifted out of the water and its yolk wobbles as much as it is still runny -->
    <section class="egg" aria-label="Egg timer" data-timer>
      <div class="egg__pan" data-pan>
        <canvas class="egg__canvas" aria-hidden="true" data-canvas></canvas>
      </div>

      <div class="egg__readout" data-readout>
        <span class="egg__time" role="timer" aria-live="off" aria-atomic="true">
          <span class="egg__digits" aria-hidden="true" data-time></span>
          <span class="sr" data-time-words></span>
        </span>
        <p class="egg__state"><span class="egg__word" data-word></span><span class="egg__detail" data-detail></span></p>
      </div>

      <fieldset class="kinds" data-kinds>
        <legend class="sr">How you like your egg</legend>
        <span class="kinds__pill" aria-hidden="true" data-pill><span class="kinds__copy" data-pill-copy></span></span>
      </fieldset>

      <div class="egg__controls" data-controls>
        <button class="egg__reset" type="button" aria-label="Start over" aria-disabled="true" data-reset>
          <span class="egg__turn">
            <svg viewBox="0 0 24 24" aria-hidden="true" data-reset-icon><path d="M5.6 9.2A7.2 7.2 0 1 1 4.9 14.2"/><path d="M5.2 4.6v4.8H10"/></svg>
          </span>
        </button>
        <button class="egg__go" type="button" data-go data-autoclic>
          <span class="egg__go-words" data-go-words>Start</span>
        </button>
        <span class="egg__balance" aria-hidden="true"></span>
      </div>

      <p class="sr" aria-live="polite" data-live></p>
    </section>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

31 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The egg timer” from Animorio and fit it into my site

What it does

On a black background a large egg cut in half lengthwise, with the thin edge of a brown shell and the point on the right: raw, the white is a dark see-through jelly with a thread of light along its top edge, and in the middle sits the orange yolk, glossy. Under it, the time in large figures, 07:00, then Ready and the temperature of the yolk, 4 °C (the egg comes out of the fridge); then the three ways to have it, Soft 5:30, Jammy 7:00 and Hard 10:00, with Jammy chosen in a light pill, and two buttons: a round one to start over, dimmed, and a yolk coloured pill with Start. Choosing another way the pill slides under it, the words change colour exactly at its edge and the figures roll to the new time. With Start the egg goes down into the water with a small dip and a burst of bubbles, starts to rock, and bubbles are born on the shell and rise; the figures run down and next to Cooking the temperature of the yolk rises. The egg really cooks: the white turns milky and then white starting from the shell, a ring closing in on the yolk, and once the heat reaches the yolk it sets from its edge too: first a darker ring, thick as jam, then pale yellow and crumbly. Pause stops everything: no more bubbles, the egg stops rocking; Resume carries on. At zero the egg is lifted out: it crouches, jumps, lands with a squash and comes back up with a bounce, and the yolk wobbles like jelly the more the runnier it is (a lot for a soft egg, barely for a hard one). Under the figures comes Done and the verdict worked out by the egg itself, runny, jammy or firm yolk, and the button turns into New egg: the cooked egg fades away and a raw one comes in. The round button starts over at any moment.

How it works

The heat, ring by ring

The cut is a half plane round the long axis of the egg: z along the egg, r out from the axis, in cells of 0.75 mm (76 by 30). Each cell is really a ring, and heat flows through its four faces in proportion to their area: outwards (i+1)/(i+½), towards the axis i/(i+½), above and below 1. It is the heat equation in cylindrical coordinates, with finite volumes, with the conductivity and the heat capacity of the white and of the yolk (a harmonic mean on the faces between the two) and the water at WATER degrees outside the shell. The time step is the longest that stays steady, and every cell remembers the highest temperature it has reached: proteins do not go back.

The colour of the highest temperature

Two tables of 481 colours, a quarter of a degree at a time, say what the temperature does: the white is clear up to 58 degrees, milky up to 66 and firm white towards 80; the yolk stays runny up to 60, turns to jam up to 65, sets up to 70 and turns pale yellow above. Two layers, the white and the yolk, are painted pixel by pixel on two hidden canvases: for each pixel the cell and the weights of the bilinear interpolation are worked out once, so painting means four reads and a table. The yolk has a wet sheen and a spot of light only where it is still runny, and a grain where it is set.

The drawing

The outline is the egg curve, y = (B/2)·√((L²−4x²)/(L²+8wx+4w²)), with w moving the widest part towards the blunt end; the skin under the shell is the same outline moved in along its normals. The white is drawn inside the outline over a black silhouette, so the bubbles passing behind do not show through the raw white; the yolk inside its circle, which can wobble on its own. The white under the yolk reads the temperature just outside the yolk, so no hole shows when the yolk squashes.

Bubbles, rocking and the jump

The bubbles are born on the shell, mostly underneath and at the sides, grow stuck to it and then let go and rise faster and faster, wobbling. The egg rocks with two sines out of step while it boils. At zero a GSAP timeline makes it crouch, jump, land squashed (the squash keeps the bottom of the egg in place) and come back up with an elastic.out; on landing the yolk swings like a damped spring, scaling (1+j, 1−j) round its centre, with its size, frequency and damping taken from how much of the yolk is still runny, so a soft egg wobbles for a while and a hard one hardly at all, and it is all over within a second and a half.

The time, the states and the preview

The time left comes from the clock (performance.now), and the egg is worked out up to where the clock says: a tab left in the background ends on time and cooked right. With DEMO the real time is squeezed (seven minutes in twenty seconds) but the egg cooks by the time on the display; the figures then change without rolling. role="timer" with aria-live off, and an aria-live region that speaks only when the state changes and at the end. The preview’s click (detail 0) only begins and resumes, and after the end it waits a little before taking a new egg.

Values to change

NameFileDefaultWhat it changes
EGGSscript.js[['Soft', 330], ['Jammy', 420], ['Hard', 600]]The ways to have the egg: the name and the seconds in the water.
CHOSENscript.js1The way chosen when the page opens: 0 is the first.
DEMOscript.js20To try it out, a whole egg cooks in this many seconds (the figures still show the real minutes); 0 = in the real time.
STARTscript.js4The egg’s temperature as it goes into the water, in degrees: 4 from the fridge, 20 from the counter (it cooks sooner).
WATERscript.js100The water, in degrees: 100 at a rolling boil; below 65 the yolk never sets.
BUBBLESscript.js1How hard the water boils round the egg: 0 = no bubbles.
WOBBLEscript.js1How much a runny yolk wobbles when the egg is lifted out: 0 = not at all.

Try them in the Playground

When to use it

For the timer of a recipe or cooking app, a smart oven or pot, a breakfast app: wherever the one waiting wants to know not only how long is left but how it is coming along. The same working out suits anything that cooks from the edge inwards (a roast, a loaf, a cake) with another shape and other temperatures.

On phones

The component is 360 pixels wide and at 390 it narrows to 358 without spilling over. The three ways are 52 pixels tall, the buttons 48 and 56. Working out the heat costs very little (about 1700 cells); the two layers are painted at most thirty times a second while the egg cooks, and never while it is still.

With reduced motion

The egg still cooks, because it is the time: the white and the yolk change colour without anything moving. No bubbles, no rocking or dip, no jump and no wobble at the end: Done and the verdict fade in. The new egg fades in, the pill of the three ways moves without sliding and the figures change without rolling.

Pitfalls

  • With the textbook conductivities the egg cooked a quarter slower than the recipes: after ten minutes the yolk of a hard egg was still runny in the middle. Recipes count on the heat that keeps going in after the egg comes out: the conductivity is raised by 30%, and the three ways come out right at the recipes’ times.
  • When the yolk wobbled, a dark crescent showed where it narrowed: the white under the yolk read the yolk’s temperatures, too low to be cooked. Now it reads the one just outside the yolk.
  • Bubbles passing behind the egg showed through the raw white, as if they were inside the egg: the egg is drawn over a black silhouette.
  • The air cell at the blunt end, drawn as a dark crescent, looked like a mistake in the drawing: it was taken out.
  • Painting the two layers pixel by pixel costs four or five milliseconds: while the egg cooks they are painted at most thirty times a second and the frames in between reuse the last painting; the cell and the weights of each pixel are worked out once.
  • In the quick try-out the figures change twenty times a second and rolling would be a smear: they roll only if the change before was more than a quarter of a second ago. And rolling with a fade the two figures overlapped half see-through: now they are a counter wheel, the new one exactly one window above the old.
  • Sliding with a bounce the pill of the three ways ran off the track at the ends, and the words changed colour all at once before the pill arrived (dark words on black for a moment). Now it slides without a bounce and inside it a dark copy of the words slides back by as much: the colour changes exactly at its edge.
  • On opening, the time and the buttons showed for a frame and then vanished to fade in: gsap.from with a delay writes its starting values on the first frame; with lazy: false it writes them at once.
  • The preview clicks by itself every 2.8 seconds and would have paused the egg just put in the water: a click from neither a hand nor the keyboard does not pause (Enter clicks with detail 0 like the script: it is told apart by its keydown). After the end it waits 2.4 seconds before taking a new egg, so the cooked egg is seen.

Libraries

GSAP 3.15.0, Rubik (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 15 KB; the libraries: GSAP 28 KB.

Testing

Tested on 7 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All components