From the documentation on list transition
This might seem like magic, but under the hood, Vue is using an animation technique called FLIP to smoothly transition elements from their old position to their new position using transforms.
From the FLIP article
FLIP stands for First, Last, Invert, Play.
Let’s break it down:
- First: the initial state of the element(s) involved in the transition.
- Last: the final state of the element(s).
- Invert: here’s the fun bit. You figure out from the first and last how the element has changed, so – say – its width, height,
opacity. Next you apply transforms and opacity changes to reverse, or
invert, them. If the element has moved 90px down between First and
Last, you would apply a transform of -90px in Y. This makes the
elements appear as though they’re still in the First position but,
crucially, they’re not.
- Play: switch on transitions for any of the properties you changed, and then remove the inversion changes. Because the element or
elements are in their final position removing the transforms and
opacities will ease them from their faux First position, out to the
Last position.
Step by step example
That way, we can inspect changes at each step of the animation process.
When it's playing in real time, the transform
is really quickly added inline and it's then removed immediately, so it looks like it's never set.
const el = document.getElementById('target');
const data = {};
function first() {
data.first = el.getBoundingClientRect();
console.log('First: get initial position', data.first.left, 'px');
}
function last() {
el.classList.toggle('last');
data.last = el.getBoundingClientRect();
console.log('Last: get new position', data.last.left, 'px');
}
function invert() {
el.style.transform = `translateX(${data.first.left - data.last.left}px)`;
console.log('Invert: applies a transform to place the item where it was.');
}
function play() {
requestAnimationFrame(() => {
el.classList.add('animate');
el.style.transform = '';
});
console.log('Play: adds the transition class and removes the transform.');
}
function end() {
el.classList.remove('animate');
console.log('End: removes the transition class.');
}
const steps = [first, last, invert, play, end];
let step = 0;
function nextStep() {
steps[step++ % steps.length]();
}
document.getElementById('next').addEventListener('click', nextStep);
.last {
margin-left: 35px;
}
.animate {
transition: transform 1s;
}
#target {
display: inline-block;
padding: 5px;
border: 1px solid #aaa;
background-color: #6c6;
}
#next {
margin-top: 5px;
}
<div id="target">target</div>
<br>
<button id="next" type="button">Next</button>