GSAP Flip — Animating DOM Layout Changes
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
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