<section class="full">scroll down</section>

<section class="banner">
  <div class="banner3d-1">
    <div class="banner3d-1-front">
      just a 3d banner<br>made with gsap<br>and scrolltrigger
    </div>
  </div>
</section>

<section class="mini"></section>

<section class="banner">
  <div class="banner3d-2">
    <div class="banner3d-2-front">
      oh that's cool<br>i didn't expect that...
    </div>
  </div>
</section>

<section class="half">scroll more</section>

<section class="banner">
  <div class="banner3d-3">
    <div class="banner3d-3-front">
      it's all<br>about<br>perspective
    </div>
  </div>
  <div class="image"></div>
</section>

<section class="half">it's not over yet</section>

<section class="banner">
  <div class="image2"></div>
  <div class="banner3d-4">
    <div class="banner3d-4-front">
      well<br>that was cool<br>but<br>it's time<br>to end<br>the show...
    </div>
  </div>
</section>

<section class="full">bisous</section>
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@800&display=swap');

body { background: white;
font-family: 'Montserrat', sans-serif;
}
section { 
  display:flex;
  justify-content:center;
  align-items:center;
  width:90%;
  max-width:800px;
  margin:0 auto;
  color:#222;
  text-transform:uppercase;
  font-size:2.8em;
  font-weight:700;
}
.full { height:100vh; background:#E0E0E0 }
.half { height:50vh; background:#E0E0E0 }
.mini { height:25vh; background:#E0E0E0 }

.banner { color: #E8E8E8; 
  display:flex;
  align-items:stretch;
}

/* first banner */

.banner3d-1 {
    width:100%;
    perspective: 700px;
    -webkit-transform-style:flat; /* why would I do that? well there is a very strange bug with safari, and it fixed it... */
    transform-style: preserve-3d;
}

.banner3d-1-front {
    padding:50px;
    background:#222;
    transform: translatez(50px);
    transform-style: preserve-3d;
}

.banner3d-1-front:before {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #BFBFBF;
    top: -50px;
    transform-origin: center bottom;
    transform: rotatex(90deg);
}

.banner3d-1-front:after {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #BFBFBF;
    bottom: -50px;
    transform-origin: center top;
    transform: rotatex(-90deg);
}

/* second banner */

.banner3d-2 {
    width:100%;
    perspective: 700px;
    -webkit-transform-style:flat;
    transform-style: preserve-3d;
  z-index:-1;
}

.banner3d-2-front {
    padding:50px;
    background:#222;
    transform: translatez(-50px);
    transform-style: preserve-3d;
}

.banner3d-2-front:before {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #BFBFBF;
    top: -50px;
    transform-origin: center bottom;
    transform: rotatex(-90deg);
}

.banner3d-2-front:after {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #BFBFBF;
    bottom: -50px;
    transform-origin: center top;
    transform: rotatex(90deg);
}

/* 3rd banner */

.banner3d-3 {
    width:50%;
    perspective: 700px;
    -webkit-transform-style:flat;
    transform-style: preserve-3d;
}

.banner3d-3-front {
    padding:100px 25px;
    text-align:center;
    background:#222;
    transform: translatez(50px);
    transform-style: preserve-3d;
}

.banner3d-3-front:before {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #404040;
    top: -50px;
    transform-origin: center bottom;
    transform: rotatex(90deg);
}

.banner3d-3-front:after {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #404040;
    bottom: -50px;
    transform-origin: center top;
    transform: rotatex(-90deg);
}

.image {
  width:50%;
  background:url(https://source.unsplash.com/IyaNci0CyRk/600x600) no-repeat;
  background-size:cover;
  background-position:center;
  box-shadow: inset 25px 0px 20px 10px rgba(0,0,0,0.41)
}


/* fourth banner */

.banner3d-4 {
    width:60%;
    perspective: 700px;
    -webkit-transform-style:flat;
    transform-style: preserve-3d;
  z-index:-1;
}

.banner3d-4-front {
    padding:25px;
    background:#222;
    transform: translatez(-50px);
    transform-style: preserve-3d;
}

.banner3d-4-front:before {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #BFBFBF;
    top: -50px;
    transform-origin: center bottom;
    transform: rotatex(-90deg);
}

.banner3d-4-front:after {
    position: absolute;
    content: "";
    width: 100%;
    left: 0;
    height: 50px;
    background-color: #BFBFBF;
    bottom: -50px;
    transform-origin: center top;
    transform: rotatex(90deg);
}

.image2 {
  width:40%;
  background:url(https://source.unsplash.com/gJJhG4gM7NA/600x600) no-repeat;
  background-size:cover;
  background-position:center center;
  border:20px solid #E0E0E0;
  box-sizing:border-box;
}

@media (max-width: 991px) {
  section {
    font-size:2em;
  }
  .banner {
    flex-direction:column
  }
  .banner3d-3, .banner3d-4 {
    width:100%
  }
  .image, .image2 {
	  width:100%;
	  height:300px;
  }
}
gsap.registerPlugin(ScrollTrigger);
gsap.set(".banner3d-1", { perspectiveOrigin: "center -100vh"});
gsap.set(".banner3d-2", { perspectiveOrigin: "center -100vh"});
gsap.set(".banner3d-3", { perspectiveOrigin: "center -100vh"});
gsap.set(".banner3d-4", { perspectiveOrigin: "left -100vh"});

gsap.to(".banner3d-1", {
  scrollTrigger: {
    trigger: ".banner3d-1",
    scrub: true,
    start: "top bottom",
    end: "bottom top"
  },
  perspectiveOrigin: "center 100vh", 
  ease: "none"
});

gsap.to(".banner3d-2", {
  scrollTrigger: {
    trigger: ".banner3d-2",
    scrub: true,
    start: "top bottom",
    end: "bottom top"
  },
  perspectiveOrigin: "center 100vh", 
  ease: "none"
});

gsap.to(".banner3d-3", {
  scrollTrigger: {
    trigger: ".banner3d-3",
    scrub: true,
    start: "top bottom",
    end: "bottom top"
  },
  perspectiveOrigin: "center 100vh", 
  ease: "none"
});

gsap.to(".banner3d-4", {
  scrollTrigger: {
    trigger: ".banner3d-4",
    scrub: true,
    start: "top bottom",
    end: "bottom top"
  },
  perspectiveOrigin: "left 100vh", 
  ease: "none"
});
Run Pen

External CSS

  1. https://codepen.io/GreenSock/pen/7ba936b34824fefdccfe2c6d9f0b740b

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.4/gsap.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.4/ScrollTrigger.min.js