Search code examples
javascripthtmlcssanimationswap

Animate DOM elements swapping


I'd like to animate the swapping of two DOM elements in a vanilla way.

I have an issue at the end of the animation but I don't know what's causing it :/

Here's my code:

HTML

<div class="container">
  <div class="child" id="childA">A</div>
  <div class="child" id="childB">B</div>
</div>

<button>Swap position</button>

JS

const childA = document.querySelector('#childA');
const childB = document.querySelector('#childB');
const finalChildAStyle = {
  x: null,
  y: null,
};
const finalChildBStyle = {
  x: null,
  y: null,
};

let swapDone = false;

document.querySelector('button').addEventListener('click', () => {
  if (swapDone === false) {
    finalChildAStyle.x = childA.getBoundingClientRect().left - childB.getBoundingClientRect().left;
    finalChildAStyle.y = childB.getBoundingClientRect().top - childA.getBoundingClientRect().top;
    finalChildBStyle.x = childB.getBoundingClientRect().left - childA.getBoundingClientRect().left;
    finalChildBStyle.y = childA.getBoundingClientRect().top - childB.getBoundingClientRect().top;
    childA.style.transform = `translate(${finalChildAStyle.x}px, ${finalChildAStyle.y}px)`;
    childB.style.transform = `translate(${finalChildBStyle.x}px, ${finalChildBStyle.y}px)`;

    setTimeout(() => {
      document.querySelector('.container').insertBefore(childB, childA);
      childB.removeAttribute('style');
      childA.removeAttribute('style');
    }, 300);
  }
  swapDone = true;
});

Here's my codepen: https://codepen.io/ChucKN0risK/pen/pLWVro

Thanks in advance ;)


Solution

  • I updated your codepen:

    https://codepen.io/anon/pen/VXMdwE

    The issue was that your css included this:

    .child {
      transition: transform ease-in 0.3s; 
    }
    

    There was actually only a specific time that you wanted the transition active on the child: in the middle of the swap process. You didn't want the transition at the end of the swap process, so I did this:

    .css:

    .child.transition {
      transition: transform ease-in 0.3s;
    }
    

    .js

    document.querySelector('button').addEventListener('click', () => {
      if (swapDone === false) {
        childA.classList.add('transition');
        childB.classList.add('transition');
    
        ...
        setTimeout(() => {
          document.querySelector('.container').insertBefore(childB, childA);
          childA.classList.remove('transition');
          childB.classList.remove('transition');
          childB.removeAttribute('style');
          childA.removeAttribute('style');
        }, 300);
    

    That way there's no longer a transition animation when you're removing the transition styles