<div>
  <div class="loading-container">
    <div class="loading"></div>
  </div>
  <div class="container">
    <div class="card-wrapper">
      <div class="card"></div>
    </div>
    <div class="card-wrapper">
      <div class="card"></div>
    </div>
    <div class="card-wrapper">
      <div class="card"></div>
    </div>
  </div>
  <script src="script.js"></script>
</div>
* {
  box-sizing: border-box;
  font-family: sans-serif;
}

body {
  background: #004b;
}

body > div {
  transform: translateY(-100px);
  transition: 0.4s 0.22s ease-in-out;
}

.d-none {
  display: none !important;
}

.container {
  padding: 20px;
}

.card-wrapper {
  perspective: 1000px;
}

.card {
  height: 200px;
  width: 100%;
  background: #fc3;
  border-radius: 20px;
  margin-bottom: 25px;
  transform-style: preserve-3d;
  transition: all 0.2s ease-out;
  box-shadow: 0px 25px 25px rgba(0, 0, 0, 0.4);
  transform: rotateX(0deg);
}

.loading-container {
  height: 100px;
  padding: 10px;
  text-align: center;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.loading-container .loading {
  width: 70px;
  height: 70px;
  border-radius: 50%;
  border: 4px solid transparent;
  border-top-color: #fff;
  border-right-color: #fff;
  animation: loading 0.5s infinite forwards;
}

@keyframes loading {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}
const pStart = { x: 0, y: 0 };
const pCurrent = { x: 0, y: 0 };
const cards = document.querySelectorAll(".card");
const main = document.querySelector("body > div");
let isLoading = false;

function loading() {
  isLoading = true;
  main.style.transform = `translateY(0px)`;
  setTimeout(() => {
    main.style.transform = `translateY(-100px)`;
    isLoading = false;
    for (const card of cards) {
      card.style.transform = `rotateX(0deg)`;
    }
  }, 2000);
}

function swipeStart(e) {
  if (typeof e["targetTouches"] !== "undefined") {
    let touch = e.targetTouches[0];
    pStart.x = touch.screenX;
    pStart.y = touch.screenY;
  } else {
    pStart.x = e.screenX;
    pStart.y = e.screenY;
  }
}

function swipeEnd(e) {
  if (document.body.scrollTop === 0 && !isLoading) {
    for (const card of cards) card.style.transform = `rotateX(0deg)`;
  }
}

function swipe(e) {
  if (typeof e["changedTouches"] !== "undefined") {
    let touch = e.changedTouches[0];
    pCurrent.x = touch.screenX;
    pCurrent.y = touch.screenY;
  } else {
    pCurrent.x = e.screenX;
    pCurrent.y = e.screenY;
  }
  let changeY = pStart.y < pCurrent.y ? Math.abs(pStart.y - pCurrent.y) : 0;
  const rotation = changeY < 100 ? changeY * 30 / 100 : 30;
  if (document.body.scrollTop === 0) {
    if (changeY > 100) loading();
    for (const card of cards) card.style.transform = `rotateX(${rotation}deg)`;
  }
}

document.addEventListener("touchstart", e => swipeStart(e), false);
document.addEventListener("touchmove", e => swipe(e), false);
document.addEventListener("touchend", e => swipeEnd(e), false);
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.