Skip to content

GSAP Flip — Animating DOM Layout Changes

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about GSAP Flip. We cover key concepts, practical examples, and best practices to help you master this topic.

GSAP Flip plugin records DOM element positions and animates smoothly to new positions after layout changes, enabling fluid list reordering and grid shuffling.

What You'll Learn

By the end of this guide, you will capture element states with Flip.getState(), animate after DOM changes with Flip.from(), reorder lists with animation, shuffle grids, animate add/remove of elements, and integrate Flip with React state changes.

Basic Flip

var state = Flip.getState('.card');

// DOM change
container.appendChild(card);

Flip.from(state, {
    duration: 0.5,
    ease: 'power2.out'
});

List Reorder

var state = Flip.getState('.list-item');

// Reorder DOM
var items = document.querySelectorAll('.list-item');
container.prepend(items[2]);

Flip.from(state, {
    duration: 0.4,
    stagger: 0.05,
    absolute: true
});

Grid Shuffle

function shuffleGrid() {
    var state = Flip.getState('.grid-item');

    var parent = document.querySelector('.grid');
    var items = Array.from(parent.children);
    for (var i = items.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        parent.appendChild(items[j]);
    }

    Flip.from(state, {
        duration: 0.6,
        ease: 'power2.inOut',
        stagger: 0.03
    });
}

Add/Remove Animation

function addItem() {
    var state = Flip.getState('.item');

    var newItem = document.createElement('div');
    newItem.textContent = 'New';
    container.appendChild(newItem);

    Flip.from(state, {
        duration: 0.4,
        ease: 'power2.out',
        absolute: true, // Animate from old position
        scale: true     // Animate scale from 0
    });
}

Common Mistakes

1. Not Getting State Before DOM Change

Flip.getState must be called BEFORE modifying the DOM. Getting state after the change captures the new positions.

2. Missing absolute Property

For elements that enter or leave the DOM, set absolute: true to correctly animate from the old position.

3. Forgetting scale for New Elements

New elements appear with no animation unless scale: true or explicit from values are set.

4. Flip on Nested Elements

Flip works on the selected elements. Nested children animate with their parent. Use self: false for children.

5. Not Calling Flip after async operations

If DOM changes happen after a setTimeout or data fetch, capture state before the async call.

Practice Questions

Q1: What does Flip.getState do? A: It records the current position, size, and rotation of selected elements.

Q2: What is the difference between Flip.from and Flip.fit? A: Flip.from animates from the old state. Flip.fit directly sets an element to match a target element's bounds.

Q3: How do you animate new elements entering the DOM? A: Use absolute: true and scale: true in Flip.from to animate from zero size at the old position.

Q4: How do you animate removed elements? A: Capture state before removal, remove the element, then use Flip.from with absolute: true. The element animates from its old position.

Q5: Can Flip animate between different parents? A: Yes. Flip tracks elements by a data-flip-id attribute and animates between parent containers.

Challenge: Build a todo list with add, remove, and reorder. Each action should animate smoothly with Flip. The checkbox should also animate when toggled.

FAQ

Does Flip work with CSS Grid?

Yes. Flip handles grid layout changes perfectly, including grid-template changes.

Can I use Flip with React?

Yes. Call Flip.getState before setState and Flip.from in the useEffect after render.

How do I set a flip ID for cross-parent tracking?

Add data-flip-id='unique-id' attributes to elements.

Can Flip animate between different states of the same element?

Yes. That is its primary use case.

Does Flip support nested flips?

Yes. Each parent and child can have independent flip animations.

Try It Yourself

Build a shuffle-able grid.

<!DOCTYPE html>
<html>
<head>
    <title>GSAP Flip Demo</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12/Flip.min.js"></script>
    <script>gsap.registerPlugin(Flip);</script>
    <style>
        .grid { display: grid; grid-template-columns: repeat(4, 80px); gap: 8px; }
        .item { width: 80px; height: 80px; background: #4ecdc4; border-radius: 8px; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 20px; }
        .item:nth-child(even) { background: #ff6b35; }
        .item:nth-child(3n) { background: #2a9d8f; }
    </style>
</head>
<body style="font-family:sans-serif;padding:20px;">
<h2>Grid Shuffle</h2>
<button onclick="shuffle()">Shuffle</button>
<button onclick="addItem()">Add Item</button>
<button onclick="removeLast()">Remove Last</button>
<div class="grid" id="grid">
    <div class="item">1</div><div class="item">2</div><div class="item">3</div><div class="item">4</div>
    <div class="item">5</div><div class="item">6</div><div class="item">7</div><div class="item">8</div>
</div>
<script>
var grid = document.getElementById('grid');

function shuffle() {
    var state = Flip.getState('.item');
    var items = Array.from(grid.children);
    for (var i = items.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        grid.appendChild(items[j]);
    }
    Flip.from(state, { duration: 0.5, ease: 'power2.inOut', stagger: 0.02 });
}

function addItem() {
    var state = Flip.getState('.item');
    var num = grid.children.length + 1;
    var item = document.createElement('div');
    item.className = 'item';
    item.textContent = num;
    grid.appendChild(item);
    Flip.from(state, { duration: 0.4, absolute: true, scale: true });
}

function removeLast() {
    if (grid.children.length === 0) return;
    var state = Flip.getState('.item');
    grid.removeChild(grid.lastChild);
    Flip.from(state, { duration: 0.3, absolute: true });
}
</script>
</body>
</html>

What's Next

Morph SVG shapes.

Morph SVG — SVG morphing with GSAP. Project — Complete GSAP project.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro