Jump to content
Search Community

ScrollTrigger stacking cards animation logic to create any effect, yes even yours!

mvaneijgen

Recommended Posts

Posted

Having cards stack is a question I see often asked on the forum and its logic is fairly simple, the only thing is you have to start with a solid foundation before you start animating things, this is not only a must for the stacking cards animation, but for animating anything!

 

First of @Cassie did a really great video on this topic that explains everything in just 2 minutes, so the TL;DR can be found here.

 

Let's walk through the process that works for me 99% of the time. Here is the starting position, we have just some HTML and CSS and we have five cards that we want to stack. If we just use it as is we’ll need to do some calculations. The first card is alright, but the second card needs to move up the height of the previous card, and the third the hight of the previous and the first card, ect. It will be possible, but it will require a lot of calculations that differ from card to card, which will make animating things a bit harder.

 

See the Pen MWxgOLa by mvaneijgen (@mvaneijgen) on CodePen.

 

What if we turn the logic around, instead of trying to calculate where to cards need to move .to() we start with them all in the same position that way we know where they are before we start animating and this is personally the approach I take with animating anything with GSAP. See below here an example, I really like @cassie’s idea of doing the stacking with Javascript, ”progressive enhancement!” (but that is an other topic), so here is just the CSS stacking all the cards right on top of each other. 

 

Instead of setting the cards to absolute, there is some clever trick with CSS Grid. The parent gets display: grid and all the elements in side get set to the same cell, now they are all on top of each other and they are still in the flow of the document, which you would lose with setting position: absolute;

 

See the Pen NWJKagv by mvaneijgen (@mvaneijgen) on CodePen.

 

Ok, now to show why this would be a great way of thinking about it.  Check it out, we can move the cards .from() any position to the center of the screen with just one tween! I hope this shows you how powerful this can be with just a few lines of code!

 

See the Pen poYzaJW by mvaneijgen (@mvaneijgen) on CodePen.

 

Quote

“Yeah, but my effect is way different. I want them to…”

Ok let's explore this further. You want to visually show that it is a stack of cards, so you need an offset at the top of your cards. Just use gsap.set() to offset the cards based on their index and done! I hope you can see that you could easily change all the x properties to y and have the effect be vertical.

 

See the Pen ExMYQyO by mvaneijgen (@mvaneijgen) on CodePen.

 

Quote

“Oh, but I want them also to scale just a little. I want to be extra fancy!”

Tell you what, I see you’re not convinced, I’ll trow in an extra perspective rotate for free! As you can see this all uses the same HTML and CSS and with just a few small tweaks to the GSAP code we can drastically change how the animation looks and feels. 

 

See the Pen MWxgQbV by mvaneijgen (@mvaneijgen) on CodePen.

 

What I hope to illustrate with all these examples is that a solid foundation of CSS will allow you to create any effect you want with just a small amount of GSAP. 

 

Wait…! We havent talked about ScrollTrigger, as you may have noticed none of the demo’s above make any use of ScrollTrigger and that has a good reason! Where we started out with just CSS the same can be said of ScrollTrigger it is a smart idea to focus on each step of the animation one at a time, so that issues don't compound when moving to fast to a new step. All ScrollTrigger is doing is animating your animation on scroll, so you first have to create a solid animation before you start to think about implementing ScrollTrigger. But all the demo’s above have ScrollTrigger logic. Just enable the ScrollTrigger code that is commented out to see how they would work.

 

Collection with even more stacking card examples

 

Ok, last one because it is so much fun! Small extra note GSAP uses a default ease: “power1.out”, which gives you animation a little flair for free, but when using ScrollTrigger with scrub: true,  it can ‘feel’ nicer to set ease: “none”. (Implemented in the last demo) Hope it helps and happy tweening!

 

See the Pen gOEYewo by mvaneijgen (@mvaneijgen) on CodePen.

  • Like 6
  • 7 months later...
Posted

 

I've gathered a lot of other effects that use this logic check out the collection on Codepen. And below a view highlights 

 

 

See the Pen dyxREEX?editors=0011 by mvaneijgen (@mvaneijgen) on CodePen.

 

See the Pen VwRBNEb by mvaneijgen (@mvaneijgen) on CodePen.

 

See the Pen abMbwYd by mvaneijgen (@mvaneijgen) on CodePen.

 

 

Here one if you don't want your cards to take up a lot of space on the page and you want to have multiple cards look like their scrolling at the same time.

 

See the Pen VYZBQpM by mvaneijgen (@mvaneijgen) on CodePen.

  • Like 3
  • 2 months later...
Posted

Hey mvaneijgen,

 

Thank you for the respond on my question, but i need help in my code i have created differently stacking card effect which i want in proper way right now it's not proper as per my code.

Thanks & Regards,

Posted

Hi,

 

You already created a thread regarding the question you have, which as stated there is not really clear:

 

On top of that your demo is not working properly since there is no scrolling on it so is not possible to test what could be the problem. We always request for a minimal demo and not a copy paste of your entire project or parts of it, just a few colored divs that clearly illustrate the problem you're having.

 

Finally please keep your questions related to this particular subject on the thread I linked above.

  • 1 month later...
Posted

mvaneijgen, you're my saver! I can't describe how I thankful to you! Good job!

  • Like 1
  • 6 months later...
Posted

hey,  i want to create a stacking effect where page 5 will come on top of page 4 after the page 4 text animation will end but a, stuck for 2 days if someone would help me it willl be really helpful 
 

import './App.css'
import gsap from 'gsap'
import { useGSAP } from '@gsap/react'
import { useRef, useEffect } from 'react'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { SplitText } from 'gsap/SplitText'
import ScrollSmoother from 'gsap/ScrollSmoother'
import Lenis from 'lenis'
 
gsap.registerPlugin(useGSAP, ScrollTrigger, SplitText, ScrollSmoother)
 
const App = () => {
  const h1Ref = useRef(null)
  const h1Ref2 = useRef(null)
 
  //lenis setup
  useEffect(() => {
    const lenis = new Lenis({
      duration: 1.2,
      easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
      smooth: true,
    })
 
    const raf = (time) => {
      lenis.raf(time)
      requestAnimationFrame(raf)
    }
 
    requestAnimationFrame(raf)
 
    return () => lenis.destroy()
  }, [])
 
  //page 1 h1 effect
  // Page 1 pin effect ->stacking effect need to use zindex
  useGSAP(() => {
    ScrollTrigger.create({
      trigger: '#page1',
      start: 'top top',
      end: 'bottom 20%', // Adjust for how long you want it pinned
      pin: true,
      pinSpacing: false,
    })
  }, [])
  //page 2 effect
  useGSAP(() => {
    const split = new SplitText(h1Ref.current, {
      type: 'chars',
    })
 
    gsap.from(split.chars, {
      scrollTrigger: {
        trigger: h1Ref.current,
        scroller: 'body',
        start: 'top 80%',
        end: 'bottom 30%',
        scrub: 1,
      },
      x: 100,
      opacity: 0,
      stagger: 0.05,
      ease: 'power3.out',
    })
  }, [])
  useGSAP(() => {
    const split = new SplitText(h1Ref2.current, {
      type: 'lines',
      linesClass: 'animated', // this adds the CSS class to each line
    })
 
    split.lines.forEach((line) => {
      gsap.to(line, {
        backgroundPositionX: 0,
        ease: 'none',
        scrollTrigger: {
          trigger: line,
          scroller: 'body',
          start: 'top 70%', //keep both value at same
          end: 'bottom 72%',
          scrub: 0.5,
        },
      })
    })
  }, [])
 
  //parallax effect for hello text
  useGSAP(() => {
    gsap.to('.hello', {
      scrollTrigger: {
        trigger: '.parallax',
        scroller: 'body',
        start: 'top 30%',
        end: 'bottom -65%',
        scrub: 1,
        pin: true,
      },
    })
  })
 
  //animating page 4
  useGSAP(() => {
    // Pin the wrapper
 
    ScrollTrigger.create({
      trigger: '#page4',
      scroller: 'body',
      start: 'top 0%',
      end: '+=1000', // longer scroll = slower animation
      pin: true,
    })
 
    // Animate .explore
    gsap.fromTo(
      '.explore',
      { x: '70%' },
      {
        x: '-100%',
        scrollTrigger: {
          trigger: '#page4',
          scroller: 'body',
          start: 'top 0%',
          end: '+=2000',
          scrub: 2, // smooth, slower motion
        },
      }
    )
    // Animate .endless
    gsap.fromTo(
      '.endless',
      { x: '-70%' },
      {
        x: '30%',
        scrollTrigger: {
          trigger: '#page4',
          scroller: 'body',
          start: 'top 10%',
          end: '+=1000',
          scrub: 2,
        },
      }
    )
   
  }, [])
 
  return (
    <div id="container">
      <div id="page1">
        <h1>Welcome</h1>
      </div>
 
      <div id="page2">
        <div className="hello">
          <h2 className="parallax">Hello</h2>
        </div>
        <div className="lorem">
          <h1 ref={h1Ref}>
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae
            eos iusto repellat esse aspernatur atque fugiat magnam obcaecati ea
            accusamus! Deleniti veritatis quidem iure sit alias, earum non ab
            quo. Lorem, ipsum dolor sit amet consectetur adipisicing elit.
            Recusandae aliquam ad culpa eum atque voluptatem quod repellat eius
            corrupti laudantium natus ipsa, iste exercitationem commodi porro
            aut facere amet deleniti.
          </h1>
        </div>
      </div>
 
      <div id="page3">
        <div className="hello"></div>
        <div className="lorem">
          <h1 ref={h1Ref2} className="animated">
            Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae
            eos iusto repellat esse aspernatur atque fugiat magnam obcaecati ea
            accusamus! Deleniti veritatis quidem iure sit alias, earum non ab
            quo.
          </h1>
        </div>
      </div>
      <div id="page4">
        <h1 className="explore">We set the bar high</h1>
        <h1 className="endless">For our Projects</h1>
      </div>
      <div id="page5"></div>
    </div>
  )
}
 
export default App
GSAP Helper
Posted

Hi @Ash_10 and welcome to the GSAP Forums!

 

Without a minimal demo, it's very difficult to troubleshoot; the issue could be caused by CSS, markup, a third party library, a 3rd party script, etc. Would you please provide a very simple CodePen or Stackblitz that illustrates the issue? 

 

Please don't include your whole project. Just some colored <div> elements and the GSAP code is best. See if you can recreate the issue with as few dependencies as possible. Start minimal and then incrementally add code bit by bit until it breaks. Usually people solve their own issues during this process! If not, at least we have a reduced test case which greatly increases your chances of getting a relevant answer.

 

See the Pen aYYOdN by GreenSock (@GreenSock) on CodePen.

that loads all the plugins. Just click "fork" at the bottom right and make your minimal demo

 

Using a framework/library like React, Vue, Next, etc.? 

CodePen isn't always ideal for these tools, so here are some Stackblitz starter templates that you can fork and import GSAP as shown in the Install Helper in our Learning Center : 

 

Please share the StackBlitz link directly to the file in question (where you've put the GSAP code) so we don't need to hunt through all the files. 

 

Once we see an isolated demo, we'll do our best to jump in and help with your GSAP-specific questions. 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...