Skip to content
animorio
IT
All components

The to-do list

Lists, Transitions, TextGSAPMediumCompressed weight: Demo 5.4 KBGSAP 28 KBFreeDownload the zip

A to-do list with real checkboxes: ticking one, the box pops, the tick draws itself, a line runs through the words and the task slides down among the ones done, lifted as if carried, while the others move up and the bar fills.

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 to-do list</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/albert-sans@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the list: real checkboxes. Ticking a task, its box pops and a tick draws itself, a line is drawn through the
         words and the task slides down among the ones done while the others move up; the bar on top fills. A task
         can be added at the top or taken away with its cross -->
    <section class="todo" aria-labelledby="todo-title" data-todo data-autoclic>
      <div class="todo__head">
        <h2 class="todo__title" id="todo-title"><span data-title>Before the guests arrive</span></h2>
        <p class="todo__count" aria-live="polite"><span data-done>0</span> of <span data-all>0</span> done</p>
      </div>
      <div class="todo__bar" aria-hidden="true"><span data-bar></span></div>
      <ul class="todo__list" data-list></ul>
      <form class="todo__add" data-add>
        <span class="todo__plus" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 6v12M6 12h12"/></svg></span>
        <input class="todo__field" type="text" placeholder="Add a task" aria-label="Add a task" maxlength="60" autocomplete="off" enterkeyhint="done" data-field>
      </form>
    </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.

21 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 to-do list” from Animorio and fit it into my site

What it does

On a black background a dark card with the title Before the guests arrive, the count 1 of 6 done, a coral bar and six tasks with their boxes, the last one, Air the rooms, already done: a coral box with a tick and grey words struck through; at the bottom, Add a task. Ticking a task the box pops with a bounce and turns coral, the tick draws itself, a line runs through the words from the left and the words dim; a moment later the task slides down among the ones done, lifted and casting a shadow, while the others move up to close the gap. The count’s number drops into place and the bar grows; with all of them done, the title becomes All done and the tasks give a little wave. Unticked, a task goes back up to its place. Typing in Add a task and pressing Enter the new task opens up at the top of the list; a task’s little cross slides it away to the right while the others move up.

How it works

Real checkboxes

Each task has a real checkbox input, see-through over the drawn box: the space bar, screen readers and forms work by themselves. The tick is a path with stroke-dasharray that draws and undraws itself; the line through the words is an element stretching with scaleX from the left and pulling back to the right.

Each task’s place

The order is always the same: first the tasks to do as they were written, then the ones done in the order they were done. After SETTLE seconds the script measures where the tasks are, puts them back in the right order and slides each one from its old place to the new one in MOVE seconds, with power3.inOut.

Carried

The task ticked rises over the others (z-index), grows by 3 per cent and gets a shadow halfway, then comes down as it arrives. A slide still going counts in the measure, so a task ticked twice in a row does not jump.

The count, the bar and the title

The number done drops into place with back.out, the bar grows with scaleX up to the part done, and when they are all done the title rolls into All done and the tasks make a 6-pixel wave, one after the other.

Adding, removing, preview

A new task goes in at the top and opens from zero height; the little cross (shown on mouse hover, always with a finger) slides it away and closes its place, and the focus goes to the next cross. A click from a script on the card (the library’s preview) ticks the first task to do; with all of them done, it unticks them all.

Values to change

NameFileDefaultWhat it changes
TASKSscript.js['Air the rooms', 'Make the beds', …]The tasks when the page opens.
START_DONEscript.js1How many of them are already done.
SETTLEscript.js0.35The pause between the tick and the task sliding to its place, in seconds.
MOVEscript.js0.6The seconds a task takes to slide to its place.

Try them in the Playground

When to use it

For a to-do list, the steps of getting ready or of a trip, a place’s cleaning between guests, a project’s tasks: wherever something gets ticked off.

On phones

The card takes the width of the screen minus a margin and long names end with an ellipsis; the little crosses always show, because without a mouse there is no hovering, and the field to add has 16-pixel text, so the page does not zoom in when it is tapped.

With reduced motion

The box and the tick change without popping and the tasks go straight to their places, without sliding; no wave at the end, and the title changes at once.

Pitfalls

  • Moving an element in the list makes it jump: the script first measures where each task is, moves it in the DOM and then slides it from the difference between the old place and the new.
  • A task still sliding must be measured together with its slide (gsap.getProperty of y): measured without it, it would start again from the wrong place.
  • A new task must be put at the top before the measuring: measured while it is not on the page yet, its starting place would be zero and it would cross the whole list.
  • Removing a task with the focus on its cross, the focus would be lost: it moves to the next task’s cross, or to the field to add.

Libraries

GSAP 3.15.0, Albert Sans (font variabile) 5.3.0.

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

Testing

Tested on 3 October 2026

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

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