<div class="card">
  <div class="images">
    <img src="https://picsum.photos/id/1/600/400" alt="actual image is irrelevant">
    <img src="https://picsum.photos/id/20/600/400?blah2" alt="actual image is irrelevant">
    <img src="https://picsum.photos/id/50/600/400?blah3" alt="actual image is irrelevant">
  </div>
</div>

<div class="card">
  <div class="images">
    <img src="https://picsum.photos/id/90/600/400?blah4" alt="actual image is irrelevant">
    <img src="https://picsum.photos/id/110/600/400?blah5" alt="actual image is irrelevant">
    <img src="https://picsum.photos/id/120/600/400?blah6" alt="actual image is irrelevant">
  </div>
</div>
.card {
  border: 1px solid #ccc;
  padding: 1rem;
  max-width: 400px;
  margin: 20px auto;
  .images {
    display: grid;
    gap: 1rem;
    grid-template:
      "top top"
      "b-l b-r";

    img:nth-child(1) {
      grid-area: top;
    }
    img:nth-child(2) {
      grid-area: b-l;
    }
    img:nth-child(3) {
      grid-area: b-r;
    }

    &.state-2 {
      img:nth-child(1) {
        grid-area: b-r;
      }
      img:nth-child(2) {
        grid-area: top;
      }
      img:nth-child(3) {
        grid-area: b-l;
      }
    }
    &.state-3 {
      img:nth-child(1) {
        grid-area: b-l;
      }
      img:nth-child(2) {
        grid-area: b-r;
      }
      img:nth-child(3) {
        grid-area: top;
      }
    }
  }
}

img {
  width: 100%;
}
View Compiled
gsap.registerPlugin(Flip);

function doFlip(el) {
  const imageParent = el.target.closest(".images");
  const allImages = imageParent.querySelectorAll("img");
  const state = Flip.getState(allImages);

  // stop the parent from collapsing
  // while the children are absolutely positioned.
  imageParent.style.height = `${imageParent.offsetHeight}px`;

  // Make DOM or styling changes
  if (imageParent.classList.contains("state-1")) {
    imageParent.classList.remove("state-1");
    imageParent.classList.add("state-2");
  } else if (imageParent.classList.contains("state-2")) {
    imageParent.classList.remove("state-2");
    imageParent.classList.add("state-3");
  } else {
    imageParent.classList.remove("state-3");
    imageParent.classList.add("state-1");
  }

  Flip.from(state, {
    duration: 1.2,
    ease: "power1.inOut",
    absolute: true, // take the images out of the document flow during flip
    onComplete: () => {
      imageParent.style.height = "unset"; // reset container height
    }
  });
}

const allImageZones = document.querySelectorAll(".images");
allImageZones.forEach((zone) => {
  zone.addEventListener("click", doFlip);
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/3.5.1/gsap.min.js
  2. https://assets.codepen.io/16327/Flip.min.js?v=3.6.0.beta20