webdevpuneet.com

FLIP List Reorder Animation — Smoothly Animating a Sort with First-Last-Invert-Play

FLIP Technique List Reorder Animation · Animations · Plain HTML, CSS & JS · Live preview

CategoryAnimations

Copy & paste

Source Code

<div class="demo">
  <div class="flip-controls">
    <button class="flip-btn" id="sortNameBtn">Sort by name</button>
    <button class="flip-btn" id="sortScoreBtn">Sort by score</button>
    <button class="flip-btn" id="shuffleBtn">Shuffle</button>
  </div>
  <ul class="flip-list" id="flipList">
    <li class="flip-item" data-id="mira"><span class="flip-name">Mira Solano</span><span class="flip-score">92</span></li>
    <li class="flip-item" data-id="devon"><span class="flip-name">Devon Ashworth</span><span class="flip-score">78</span></li>
    <li class="flip-item" data-id="lena"><span class="flip-name">Lena Okafor</span><span class="flip-score">95</span></li>
    <li class="flip-item" data-id="priya"><span class="flip-name">Priya Nair</span><span class="flip-score">64</span></li>
    <li class="flip-item" data-id="theo"><span class="flip-name">Theo Bergstrom</span><span class="flip-score">88</span></li>
  </ul>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Genuine First-Last-Invert-Play implementation, not a simplified approximation
Reusable flipReorder() helper accepts any DOM-mutating reorder function, decoupling the animation logic from the sort logic
Only transform is animated — compositor-thread friendly, smooth even when many items move simultaneously
Forced reflow (getBoundingClientRect()) correctly used to guarantee the invert step is applied before the transition starts
Works for sort-by-name, sort-by-score, and random shuffle using the exact same underlying animation code
No animation library — pure vanilla JavaScript and CSS transforms
will-change: transform hints the browser to optimize for the upcoming animated property
Generalizes directly to other DOM-reordering scenarios beyond sorting (filtering, insertion, removal)

About this UI Snippet

FLIP List Reorder Animation — Animating Position Changes You Can't Directly Animate

Screenshot of the FLIP Technique List Reorder Animation snippet rendered live

Sorting a list by re-appending its DOM elements in a new order is instant and abrupt — every item jumps to its new position with no visual continuity. FLIP (First, Last, Invert, Play) is the standard technique for turning that jump into a smooth slide, and it works for exactly this kind of change: one where you *can't* animate the property directly (DOM order isn't animatable), but you *can* animate a cheap visual stand-in (a transform) that fakes the same motion.

First: measuring where everything starts

Before touching the DOM, flipReorder() records every item's current getBoundingClientRect() into a Map keyed by the element itself. This is the "First" position — a snapshot taken while the list is still in its old, pre-sort order.

The actual reorder is real and instant, on purpose

reorderFn(items) — whichever sort or shuffle function was passed in — genuinely re-appends every list item into its new DOM order using real appendChild calls. This is the "expensive," layout-triggering step, and it's allowed to happen instantly and messily; FLIP doesn't try to animate the reorder itself, only to disguise its visual result.

Last, Invert: making the jump invisible for one frame

Immediately after the reorder, each element's *new* position is measured (Last), and the delta between old and new position is computed. Setting transform: translate(deltaX, deltaY) with transition: none snaps the element visually back to exactly where it was before the reorder — so even though the DOM has already changed, nothing appears to move yet. This is the "Invert" step: using a transform to counteract the position change that already happened.

Play: animating only a transform, which is cheap

The forced el.getBoundingClientRect() read between setting the inverted transform and clearing it is a well-known trick to force the browser to actually apply the "snap back" styles before the next change — without it, the browser could batch both style changes together and skip the transition entirely. Once that reflow is forced, re-enabling transition and clearing the transform (el.style.transform = '') lets the browser smoothly animate from the inverted position back to the real, final position — and because only transform is animating (not top/left/DOM order), this runs on the compositor thread, staying smooth even while re-sorting many items simultaneously.

Why this generalizes beyond sorting

FLIP works for any change that repositions elements without a directly animatable CSS property behind it — filtering a grid, removing an item and having the rest collapse upward, or reflowing a masonry layout. The technique here (measure, mutate, measure again, invert, play) is the same regardless of *what* caused the reorder.

Step by step

How to Use

  1. 1
    Click any sort/shuffle buttonWatch every row smoothly slide to its new position rather than instantly jumping there.
  2. 2
    Write your own reorder functionAny function that takes the current items array and re-appends them to the list in a new order works with flipReorder() — no changes to the FLIP logic itself needed.
  3. 3
    Adjust the animation timingChange the transition's duration and cubic-bezier easing in the PLAY step to taste.
  4. 4
    Add or remove list itemsThe FLIP measurement logic works on whatever .flip-item elements currently exist — no fixed count assumed.
  5. 5
    Reuse the flipReorder helper for filteringThe same First/Last/Invert/Play helper works for any DOM mutation that repositions elements, not just sorting — e.g. showing/hiding filtered items.

Real-world uses

Common Use Cases

Sortable Lists and Leaderboards
Animate rows sliding to their new rank whenever a leaderboard or sortable list is re-sorted.
Filtered Grid/List Reflow
Smoothly animate remaining items sliding into the gaps left by filtered-out items.
KANBAN
Kanban / Drag-Drop Reordering
Animate the settling motion of other items when one is dropped into a new position.
EDUCATION
Teaching the FLIP Technique
A clean, well-commented reference implementation of FLIP for anyone learning the pattern.
Related: Magnetic Grid
See the Magnetic Grid for a related animations pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

First (measure every element's starting position), Last (measure its ending position after the real, instant DOM mutation), Invert (use a transform to make the element appear to still be in its First position even though it's now actually in its Last position), and Play (animate that transform back to zero, so the element visibly slides from First to Last).

DOM order and layout position aren't CSS properties that can be transitioned — there's no way to animate "this element's index in its parent." FLIP works around that by letting the reorder happen instantly and disguising the resulting jump with an animated transform instead.

Browsers often batch consecutive style changes together for performance. Without forcing a reflow between setting the inverted transform (with transitions disabled) and then clearing it (with transitions enabled), the browser could apply both changes in the same paint and skip the animation entirely — the forced read guarantees the "snapped back" state is actually rendered first.

Yes — because every animated element only transitions its own transform property (not top/left, which would trigger layout), each animation runs independently on the compositor thread, keeping performance smooth even when most or all items in the list change position simultaneously.

Yes — the same flipReorder() helper works for any function that mutates the DOM in a way that repositions existing elements, including removing an item and letting the rest collapse into the gap, or inserting a new item and having existing ones shift to make room.

No — reorder functions like sortByName or shuffle are completely unaware of the animation; they just mutate the DOM directly and normally. All FLIP-specific logic (measuring, inverting, animating) lives entirely inside flipReorder() itself, keeping the two concerns cleanly separated.