<link href='//fonts.googleapis.com/css?family=Signika+Negative:300,400' rel='stylesheet' type='text/css'>
<h1>GSAP FLIP Demo</h1>
<div id="flex">
  <div id="container1">
    <div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div>
  </div>
  <div id="container2"></div>
</div>
body {
  color: white;
  background-color: black;
  padding: 0 20px;
  font-family: 'Signika Negative';
}
#flex {
  display: flex;
  overflow: hidden;
}
#container1, #container2 {
  width: 50%;
}
#container1 div, #container2 div {
  margin-bottom: 3px;
  height: 26px;
  background-color: #777;
  border-radius: 13px;
  border: 1px solid #333;
  text-align: center;
}
flip("#container1 div", doMyStuff, {stagger: 0.1, duration: 1.5, ease: "elastic", delay: 1});

/* 
Copy this to your project. Pass in the elements (selector text or NodeList or Array), 
then a function/callback that actually performs your DOM changes, and optionally a vars 
object that contains any of the following properties to customize the transition:

 - duration [Number] - duration (in seconds) of each animation
 - stagger [Number | Object | Function] - amount to stagger the starting time of each animation. You may use advanceds staggers too (see https://codepen.io/GreenSock/pen/jdawKx)
 - ease [Ease] - controls the easing of the animation. Like "power2.inOut", or "elastic", etc.
 - onComplete [Function] - a callback function that should be called when all the animation has completed.
 - delay [Number] - time (in seconds) that should elapse before any of the animations begin. 

This function will return a Timeline containing all the animations. 
*/
function flip(elements, changeFunc, vars) {
  elements = gsap.utils.toArray(elements);
  vars = vars || {};
  let tl = gsap.timeline({onComplete: vars.onComplete, delay: vars.delay || 0}),
      bounds = elements.map(element => {
        let b = element.getBoundingClientRect();
        element._flip && element._flip.progress(1);
        element._flip = tl;
        return b;
      }),
      copy = {},
      p;
  changeFunc();
  for (p in vars) {
    p !== "onComplete" && p !== "delay" && (copy[p] = vars[p]);
  }
  copy.x = (i, element) => "+=" + (bounds[i].left - element.getBoundingClientRect().left);
  copy.y = (i, element) => "+=" + (bounds[i].top - element.getBoundingClientRect().top);
  return tl.from(elements, copy);
}


//this function just takes all the <div> elements from #container1 and puts them into #container2 in a randomized order. 
function doMyStuff() {
  var elements = gsap.utils.toArray("#container1 div"),
      newContainer = document.querySelector("#container2"),
      i;
  elements.sort(function() { return 0.5 - Math.random(); });
  for (i = 0; i < elements.length; i++) {
    newContainer.appendChild(elements[i]);
  }
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js