JSFiddle - React, Tailwind, and code Playground

by HDL52

HTML

<body>
  <div class="emptybox">empty</div>
  <div class="emptybox">empty</div>
  <div class="scrollbox">
    <div class="scrollbox_container">
      <div class="scrollbox_container_card">
        <p>card one</p>
      </div>
      <div class="scrollbox_container_card">
        <p>card two</p>
      </div>
      <div class="scrollbox_container_card">
        <p>card three</p>
      </div>
    </div>
  </div>
  <div class="emptybox">empty</div>
  <div class="emptybox">empty</div>
</body>

CSS

* {
  padding: 0;
  margin: 0;
  font-size: 2vmin;
}

p,
img {
  pointer-events: none;
  user-select: none;
}

div {
  display: flex;
  justify-content: center;
  align-items: center;
  user-select: none;
}

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  background-color: #171717;
}

.emptybox {
  width: 65rem;
  height: 40rem;
  background-color: #17f700;
  border-radius: 5rem;
  margin-bottom: 8rem;
  font-family: sans-serif;
  font-size: 8rem;
  color: #f7f7f7;
  font-weight: 900;
  text-transform: uppercase;
}

.scrollbox {
  justify-content: start;
  align-items: start;
  width: 100%;
  overflow: hidden;
}

.scrollbox_container {
  justify-content: start;
  height: 100vh;
  flex-shrink: 0;
}

.scrollbox_container_card {
  position: relative;
  width: 65rem;
  height: 40rem;
  background-color: #f7f7f7;
  border-radius: 5rem;
  margin-left: 5rem;
  flex-shrink: 0;
  overflow: hidden;
}

.scrollbox_container_card p {
  font-family: sans-serif;
  font-size: 6rem;
  color: #171717;
  font-weight: 900;
  text-transform: uppercase;
  z-index: 1
}

JavaScript

const scrollbox = {
  container: document.querySelector('.scrollbox_container'),
  cards: [...document.querySelectorAll('.scrollbox_container_card')],
  trigger_distance: 0,
  border_distance: 0,
  distance: 0,
  resize() {
    let _scrollbox = document.querySelector('.scrollbox');
    _scrollbox.style.height = `${this.container.offsetWidth}px`;
    this.trigger_distance = _scrollbox.offsetTop;
    this.border_distance = _scrollbox.offsetTop + _scrollbox.offsetHeight - innerHeight;
  },
  move() {
    if (scrollY >= this.trigger_distance && scrollY <= this.border_distance) {
      this.distance = scrollY - this.trigger_distance;
      this.container.style.transform = `translateY(${this.distance}px)`;
      let distance_x = this.distance / (this.border_distance - this.trigger_distance) * (this.container.offsetWidth - innerWidth);
      for (let i = 0; i < this.cards.length; i++) {
        this.cards[i].style.transform = `translateX(${-distance_x}px)`;
      }
    }
  }
};

scrollbox.resize()

window.addEventListener("resize", () => {
  scrollbox.resize()
})

window.addEventListener("scroll", () => {
  scrollbox.move()
})