Jump to content
Search Community

GSAP Flip and ScrollTrigger get rigth initial position with a sticky and other animations

serhiiL test
Moderator Tag

Go to solution Solved by serhiiL,

Recommended Posts

Posted (edited)

Hi GSAP Community,

I am working on an animation where an element (targetEl) moves between different zones (zoneEl) as the user scrolls. However, I'm facing an issue with tracking the initial position of targetEl correctly. The targetEl is inside zoneEl.first(), which is in another div with a height of 1500dvh and is animated to move from right to left by -100dvh. This movement is causing the targetEl to start in the wrong position, and the animation does not play correctly.

Here is the code I am using (fille in attaches):

window.addEventListener("DOMContentLoaded", (event) => {
  gsap.registerPlugin(ScrollTrigger, Flip);

  let zoneEl = $("[js-scrollflip-element='zone']"),
      targetEl = $("[js-scrollflip-element='target']").first();

  let tl;
  function createTimeline() {
    if (tl) {
      gsap.set(targetEl, { clearProps: "all" });

    tl = gsap.timeline({
      scrollTrigger: {
        trigger: zoneEl.first(),
        start: "center center",
        endTrigger: zoneEl.last(),
        end: "center center",
        scrub: true

    zoneEl.each(function (index) {
      let nextZoneEl = zoneEl.eq(index + 1);
      if (nextZoneEl.length) {
        let nextZoneDistance =
          nextZoneEl.offset().top + nextZoneEl.innerHeight() / 2;
        let thisZoneDistance = $(this).offset().top + $(this).innerHeight() / 2;
        let zoneDifference = nextZoneDistance - thisZoneDistance;

          Flip.fit(targetEl[0], nextZoneEl[0], {
            duration: zoneDifference,
            ease: "power2.inOut"


  let resizeTimer;
  window.addEventListener("resize", function () {
    resizeTimer = setTimeout(function () {
    }, 250);


The problem is that targetEl is positioned incorrectly because zoneEl.first() is animated with a -100dvh shift from right to left. I need to track the initial position of targetEl correctly so that the animation starts at the correct position with the right coordinates and dimensions.

I have included a video explanation and a link to my site for more context:
Video: https://www.loom.com/share/9bfb3434afcc432b8fb6ab969bed136c?sid=188e85ea-b5a8-42f3-bd02-f52f103f7b57
Website: https://s-liudvichenko.webflow.io

Any help or suggestions would be greatly appreciated!

Thank you!


See the Pen JjqNvyP by SL-Fama (@SL-Fama) on CodePen

Edited by serhiiL
Added Codepen project
Link to comment
Share on other sites

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 the gsap-trial NPM package for using any of the bonus plugins: 


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. 

Link to comment
Share on other sites



I'm having a hard time following the logic behind your demo, plus you have some CSS Transitions in it as well. Also there is no scrolling available in your demo but for some reason as I scroll down more and more scrolling becomes available (the scroll bar becomes smaller and smaller). I think you have to review your HTML and CSS in order to make this work. Maybe a simpler approach could be a better fit for this situation.


This demo is a demonstration of how this works:

See the Pen JjVPyxd by GreenSock (@GreenSock) on CodePen


Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Hey @Rodrigo. I apologize for that, but it was necessary to show the issue I was facing (I've updated my Codepen so it should scroll correctly now).


The problem is that my trigger is placed in a div with sticky positioning and an animation that moves it from right to left. Because of this, the initial position was captured incorrectly.

I'm wondering if there's a way to set the initial state of the trigger when the animation begins, or to track the position of the target while it animates and scrolls inside the parent div. Are there any GSAP techniques for handling dynamically changing positions of animated elements?

Thanks in advance for your help!

Link to comment
Share on other sites

2 hours ago, serhiiL said:

The problem is that my trigger is placed in a div with sticky positioning

Yep this is something you can't do, if you want to elements to stick, you'll have to let ScrollTrigger handle all the stickiness with using the pin feature in ScrollTrigger, you cant have position: sticky; on an element and use ScrollTrigger on it.

Link to comment
Share on other sites

While a more convoluted setup can be achieved, that would require a lot of custom logic and that is a bit beyond the scope of what we do in these free forums, since we don't have the time resources to create custom solutions for our users or solve complex logic issues.


At it's core, Flip.fit() will get the states of both elements and animate the first to match the second. The issue here is when is done, not how is done. This is happening while there is another animation that changes the position after those Flip.fit() instances have been created, so naturally that messes all those calculations.


In the demo I have there is no initial animation so everything is in it's final position at the start, when the states for the second and third targets are created using getState(). That's why I suggested a simpler approach in my previous post.


Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

  • Solution

Hello @Rodrigo, @mvaneijgen. I know this isn't a common case, so that's okay. Thank you for your time anyway.

I handled it by creating a new timeline to capture the position when a specific element enters into view.

// Trigger a function when the position element enters the viewport
   trigger: positionEl,
   start: "top bottom",
   onEnter: function () {
     // Execute the createTimeline function when positionEl enters the viewport

I know it’s not the most elegant solution, but it works for my case.
The Codepen has been updated as well, in case someone needs such a weird solution.


Link to comment
Share on other sites

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...