<h1>ScrollTrigger.batch()</h1>

<div class="container">
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
  <div class="box red"></div>
  <div class="box purple"></div>
  <div class="box orange"></div>
  <div class="box green"></div>
  <div class="box gray"></div>
  
</div>






<header>
   <a href="https://greensock.com/scrolltrigger">
     <img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/scroll-trigger-logo-light.svg" width="200" height="64" />
  </a> 
</header>
body {
  background-color: #222;
  text-align: center;
  font-family: "Signika Negative", Arial, sans-serif;
  color: white;
}

h1 {
  font-weight: 400;
  font-size: 2.5em;
}

.container {
  max-width: 800px;
  margin: auto;
  width: 100%;
  line-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
}

.box {
  width: 31%;
  height: 15vh;
  margin: 5px;
  opacity: 0;
  will-change: transform;
}


.gray {
  background-color: #777;
}
.blue {
  background-color: #2c7ad2;
}
.orange {
  background-color: #e77614;
}
.red {
  background-color: #c82736;
}
.purple {
  background-color: #8d3dae;
}
.green {
  background-color: #28a92b;
}


header {
  position: fixed;
  top: 0px;
  left: 0px;
  padding: 6px 10px 6px 10px;
  border-bottom-right-radius: 26px;
  z-index: 100;
  background-color: rgba(0,0,0,0.5);
}
gsap.defaults({ease: "power3"});
gsap.set(".box", {y: 100});

ScrollTrigger.batch(".box", {
  //interval: 0.1, // time window (in seconds) for batching to occur. 
  //batchMax: 3,   // maximum batch size (targets)
  onEnter: batch => gsap.to(batch, {opacity: 1, y: 0, stagger: {each: 0.15, grid: [1, 3]}, overwrite: true}),
  onLeave: batch => gsap.set(batch, {opacity: 0, y: -100, overwrite: true}),
  onEnterBack: batch => gsap.to(batch, {opacity: 1, y: 0, stagger: 0.15, overwrite: true}),
  onLeaveBack: batch => gsap.set(batch, {opacity: 0, y: 100, overwrite: true})
  // you can also define things like start, end, etc.
});


// when ScrollTrigger does a refresh(), it maps all the positioning data which 
// factors in transforms, but in this example we're initially setting all the ".box"
// elements to a "y" of 100 solely for the animation in which would throw off the normal 
// positioning, so we use a "refreshInit" listener to reset the y temporarily. When we 
// return a gsap.set() in the listener, it'll automatically revert it after the refresh()!
ScrollTrigger.addEventListener("refreshInit", () => gsap.set(".box", {y: 0}));

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

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