Jump to content
Search Community

Card Stacking not working Properly.

dotsinspace test
Moderator Tag

Recommended Posts

I am just trying to stack cards on scroll just like this : 

Now Issue i am getting is that i just cant make it on react. reason things getting messy and buggy everytime shown in following video.

https://imgur.com/a/aOPy9bh

NOTE: After watch this video i know some of you might not like the way i asked the question but i can't really write code pen of this issue. as i already know that there is some issue with my css might be..but still i cant figure out the actual problem.

After some recherché i found out that this issue might be with position: fixed and transform property.

If you guys need to see code then please do let me know.

Source Code:

/*
 * IMPORTS
 */
import React from 'react' // NPM: react.js library.
import Image from 'next/image' // NPM: optimized image component from next.js.
import { gsap } from 'gsap' // NPM: animation library.
import { BsArrowRight } from 'react-icons/bs' // NPM: react-icons library for icons.
import Dynamic from 'next/dynamic' // NPM: next.js dynamic component utility.


/*
 * STYLES
 */
import ContainerWrapper, {
  BulletsContainer,
  ContentContainer,
  ServiceImageContainer,
  ServiceInformationWrapper,
  ServiceWrapper,
  SlideContainer,
  SlidesContainer,
  Technologies
} from './index.style'


/*
 * COMPONENTS
 */
const Container = Dynamic(() => import('reusecore/src/elements/Container'))
const Text = Dynamic(() => import('reusecore/src/elements/Text'))
const Heading = Dynamic(() => import('reusecore/src/elements/Heading'))


/*
 * OBJECTS
 */
const Index = () => {
  // Const Assignment
  const _data = [
    {
      'heading': 'Web Development',
      'subHeading': 'Our Latest Web Development Projects',
      'image': [
        {
          image: '/static/image/Night-Googles.png',
          name: 'Garbit'
        },
        {
          image: '/static/image/HealthcareFirm.png',
          name: 'Voice ( InHouse )'
        }
      ],
      'info': 'UX (User Experience) design starts with a deep understanding of both user challenges and business goals.Its a concept that goes hand-in-hand with the UI design phase of a project because the final product must be efficient, fluid, and easy to understand but not strictly pragmatic.',
      'technologies': [
        '/static/image/technologies/react.svg',
        '/static/image/technologies/graphql.svg',
        '/static/image/technologies/next.svg',
        '/static/image/technologies/vercel.svg',
        '/static/image/technologies/googleCloud.svg',
        '/static/image/technologies/postgresql.svg'
      ]
    },
    {
      'heading': 'UI/UX Design',
      'subHeading': 'Our Latest UI/UX Design Projects',
      'image': [
        {
          image: '/static/image/Night-Googles.png',
          name: 'Night Googles'
        },
        {
          image: '/static/image/HealthcareFirm.png',
          name: 'Healthcare Firm'
        }
      ],
      'info': 'UX (User Experience) design starts with a deep understanding of both user challenges and business goals.Its a concept that goes hand-in-hand with the UI design phase of a project because the final product must be efficient, fluid, and easy to understand but not strictly pragmatic.',
      'technologies': ['/static/image/technologies/illustrator.svg', '/static/image/technologies/figma.svg', '/static/image/technologies/photoshop.svg']
    },
    {
      'heading': 'App Development',
      'subHeading': 'Our Latest App Development Projects',
      'image': [
        {
          image: '/static/image/Night-Googles.png',
          name: 'Night Googles'
        },
        {
          image: '/static/image/HealthcareFirm.png',
          name: 'Healthcare Firm'
        }
      ],
      'info': 'UX (User Experience) design starts with a deep understanding of both user challenges and business goals.Its a concept that goes hand-in-hand with the UI design phase of a project because the final product must be efficient, fluid, and easy to understand but not strictly pragmatic.',
      'technologies': ['/static/image/technologies/android.svg', '/static/image/technologies/apple.svg', '/static/image/technologies/react.svg']
    }
  ]

  // Event handler.
  React.useEffect(() => {
    // Object assignment.
    const ScrollTrigger = require('gsap/ScrollTrigger').default

    // Register gsap plugin.
    gsap.registerPlugin(ScrollTrigger)

    gsap.fromTo(
      '.serviceCard:not(:first-child)',
      {
        'y': () => window.innerHeight
      },
      {
        'y': 0,
        'stagger': 0.5,
        'scrollTrigger': {
          'pin': '.serviceCard',
          'markers': true,
          'scrub': true,
          'start': 'top center',
          'end': 'bottom top',
          'invalidateOnRefresh': true
        }
      }
    )
  })


  // Return Component.
  return (
    <Container noGutter width='1300px'>
      <ContainerWrapper>
        <BulletsContainer>
          <span></span>
          <span className='active'></span>
          <span></span>
          <span></span>
        </BulletsContainer>
        <SlidesContainer id='c'>
          {
            _data.map((x, index) => (
              <SlideContainer className='serviceCard' key={String.random(8)}>
                <Text className='description font gradient position unset' content={`0${index + 1}`}/>
                <Heading className='heading font white' content={x.heading}/>
                <ContentContainer>
                  <ServiceWrapper>
                    <Text className='subHeading width maxContent transparent font capitalize' content={x.subHeading} />
                    <ServiceImageContainer>
                      {
                        x.image.map(({ image, name }) => (
                          <div className='nightGoogle' style={{
                            backgroundImage: `url(${image})`,
                            backgroundRepeat: 'no-repeat'
                          }}>
                            <p>{name}</p>
                          </div>
                        ))
                      }
                    </ServiceImageContainer>
                    <button className='reusecore__button theme gradientRound' style={{ marginTop: '50px !important' }}>
                      <span>View All</span> <BsArrowRight/>
                    </button>
                  </ServiceWrapper>
                  <ServiceInformationWrapper>
                    <Text className='description font white' content={x.info} />
                    <Text className='subHeading width maxContent transparent' content='Technologies' />
                    <Technologies>
                      {
                        x.technologies.map((item, idx) => (
                          <Image key={idx} src={item} alt='technologies' height={31} width={31} />
                        ))
                      }
                    </Technologies>
                  </ServiceInformationWrapper>
                </ContentContainer>
              </SlideContainer>
            ))
          }
        </SlidesContainer>
      </ContainerWrapper>
    </Container>
  )
}


/*
 * EXPORTS
 */
export default Index

StyleComponent.

/*
 * IMPORTS
 */
import Dynamic from 'next/dynamic' // NPM: next.js dynamic component utility.
import styled from 'styled-components' // NPM: react.js styled library
import ThemeGet from '@styled-system/theme-get' // NPM: styled-system library from react.js


/*
 * COMPONENTS
 */
const Box = Dynamic(() => import('reusecore/src/elements/Box'))


/*
 * OBJECTS
 */
const ContainerWrapper = styled(Box)`
  position: relative;
  width: 100%;
  height: 100%;
`
const SlideContainer = styled(Box)`
  margin: 20px 0;
  background-color: ${ThemeGet('colors.lightestBlack')};
  padding: 50px 100px;
  border-radius: 25px;
  width: 100%;
  transition: position 0.3s;
  box-shadow: 0 0 100px 30px ${ThemeGet('colors.blackShadow')};
  overflow: hidden;
  & > .description {
    font-size: 41px !important;
    margin: 0 !important;
    height: unset !important;
  }

  & > .heading {
    margin-top: 0px !important;
    margin-left: 20px !important;
  }
`
const SlidesContainer = styled(Box)`
  position: relative;
  height: 150vh;
  width: 100%;
`
const ContentContainer = styled(Box)`
  display: flex;
  justify-content: flex-start;
  margin-top: 30px !important;
  & .subHeading {
    font-size: 13px !important;
    padding-left: 0 !important;
  }
`
const ServiceInformationWrapper = styled(Box)`
  flex: 1;
  & .description {
    width: 100%;
    padding: 0 0 30px 0;
    margin-bottom: 30px;
    border-bottom: 2px solid ${ThemeGet('colors.lightBlack')};
  }
`
const ServiceWrapper = styled(Box)`
  flex: 1;

  & > .subHeading {
    font-size: 17px !important;
    padding: 20px 0 !important;
  }

  & > .reusecore__button {
    margin-top: 40px !important;
    margin-left: 0 !important;
  }
`
const ServiceImageContainer = styled(Box)``
const Technologies = styled(Box)`
  display: flex;
  gap: 15px;

  & img {
    width: 35px;
    height: 35px;
    border-radius: 8px;
    overflow: hidden;
    background-size: cover;
    background-color: ${ThemeGet('colors.lightBlack')};
    padding: 10px;
  }
`
const BulletsContainer = styled(Box)`
  display: flex;
  flex-direction: column;
  width: 70px;
  gap: 10px;
  align-items: center;
  justify-content: center;

  & span {
    width: 10px;
    height: 10px;
    border-radius: 100%;
    background-color: ${ThemeGet('colors.white')};

    &.active {
      background-color: ${ThemeGet('colors.primary')};
    }

    &:first-child {
      width: 2px;
      height: 150px;
      border-radius: 0;
      left: 5px;
      position: relative;
      background-color: ${ThemeGet('colors.lightestBlack')};
    }
  }
`


/*
 * EXPORTS
 */
export default ContainerWrapper
export {
  BulletsContainer,
  ContentContainer,
  SlideContainer,
  SlidesContainer,
  ServiceImageContainer,
  ServiceInformationWrapper,
  ServiceWrapper,
  Technologies
}

 

See the Pen GRBvayM by dotsinspace (@dotsinspace) on CodePen

Link to comment
Share on other sites

Without seeing code it's nearly impossible to tell what you're doing.... If the example is your codepen, I'm not sure why you're transforming and pinning the cards, you should be able to just pin it using ScrollTrigger (no need to create a timeline). You'll also want to setup a loop for this, as a single timeline or ScrollTrigger wont seperate the cards out (unless you use Batch).

Link to comment
Share on other sites

11 minutes ago, elegantseagulls said:

Without seeing code it's nearly impossible to tell what you're doing.... If the example is your codepen, I'm not sure why you're transforming and pinning the cards, you should be able to just pin it using ScrollTrigger (no need to create a timeline). You'll also want to setup a loop for this, as a single timeline or ScrollTrigger wont seperate the cards out (unless you use Batch).

Done Please Help

Link to comment
Share on other sites

It's very difficult to troubleshoot without a minimal demo that clearly shows the problem (your CodePen was working correctly, right?) but one issue for sure is that you're not doing proper clean up in React which is essential because React 18 calls useEffect()/useLayoutEffect() TWICE in strict mode and that can case you to inadvertently create multiple competing tweens/ScrollTriggers. 

 

gsap.context() is your new best friend in React because it makes cleanup super easy. Please read this article: 

 

 

Try wrapping your GSAP-related code in a gsap.context() and do proper cleanup by returning a cleanup function that calls .revert() on your context and then let us know if that resolves things for you. If not, please provide a minimal demo that clearly illustrates the problem. Here's a Stackblitz that you can fork: https://stackblitz.com/edit/react-cxv92j

Link to comment
Share on other sites

14 minutes ago, dotsinspace said:

thats impossible...because if had found the problem then it will resolved until now

I didn't understand your comment. Are you saying you followed my advice and did proper cleanup with a gsap.context() and it still didn't work? 

 

14 minutes ago, dotsinspace said:

can i share ngrok link so that you can checkout live issue

That won't really help. We cannot re-compile a React project from a live site like that. If you want help with this issue, the best path to accomplishing that is for you to create a CodeSandbox or Stackblitz that clearly illustrates the issue so that we can actually see the code in context, make tweaks and identify exactly what's going on. When you share a live site, there are just way too many factors involved - it could be a 3rd party library causing problems, CSS, HTML structure, etc. It's not usually feasible to troubleshoot live sites like that. Is there a reason you can't provide a minimal demo

Link to comment
Share on other sites

30 minutes ago, dotsinspace said:

Does multiple registration of scrolltrigger causes wiered scroll up or down ?.

It shouldn't as far as I can tell. We've seen plenty of examples from users where they register a plugin on every file it's used without that causing many issues. Is completely not necessary, just registering all the plugins at a top level file is enough in this type of setups.

 

Are you actually using GSAP Context in your setup? In this it seems that you don't:

React.useEffect(() => {
  gsap.fromTo(
    '.serviceCard:not(:first-child)',
    {
      'y': () => window.innerHeight
    },
    {
      'y': 0,
      'stagger': 0.5,
      'scrollTrigger': {
        'pin': '.serviceCard',
        'markers': true,
        'scrub': true,
        'start': 'top center',
        'end': 'bottom top',
        'invalidateOnRefresh': true
      }
    }
  )
})

Also you're using require for getting ScrollTrigger inside the useEffect layout. Any particular reason for not using an import statement at the top of the file?

React.useEffect(() => {
  // Object assignment.
  const ScrollTrigger = require('gsap/ScrollTrigger').default

  // Register gsap plugin.
  gsap.registerPlugin(ScrollTrigger)
})

Like  I said before, there isn't a lot of issues in registering the plugin more than once, is not needed but that shouldn't cause an issue. But making a require statement inside a React Hook is something I haven't seen before. Just import ScrollTrigger at the top of your file and that should do it.

 

35 minutes ago, dotsinspace said:

And one more thing is there any way to stack cards without scrollTrigger on scrolling. ?

Can you be a bit more explicit about this?

 

Happy Tweening!

Link to comment
Share on other sites

Just now, dotsinspace said:

error -> cannot use import statement outside a module

That doesn't tell me anything. Once again, what are you using for bundling your app?

 

Ok, for your last comment there's the error. The import should be like this:

import { ScrollTrigger } from "gsap/ScrollTrigger";

Got to this link and scroll down a bit. You'll find a section called GSAP 3 Install Helper:

https://greensock.com/docs/v3/Installation

 

Happy Tweening!

Link to comment
Share on other sites

8 hours ago, dotsinspace said:

Does multiple registration of scrolltrigger causes wiered scroll up or down ?..if Yes then i have found the cuplrit..

Just to confirm what @Rodrigo said, it's totally fine to register a plugin multiple times. That will have no negative effects. 

 

I'm sure once we see a minimal demo that clearly shows the problem, we'll be able to offer some advice. It's just very difficult to troubleshoot blind.

 

7 hours ago, dotsinspace said:

😅 error -> cannot use import statement outside a module

That sure sounds like you're not using a bundler or build tool and you're actually using a standard <script> tag where you're trying to do imports right in the browser. If that's true, keep in mind that you must set type="module" on your <script> tag and also use relative paths for your imports. It may be easier for you to just load the .min.js (minified ES5 UMD) files via a normal <script> tag instead of trying to do imports if you're not very familiar with how to do those. It's up to you, of course. GSAP can be loaded via a multitude of ways. 

Link to comment
Share on other sites

2 hours ago, dotsinspace said:

I am using next.js which comes with webpack. and i am importing it just like told in installation process.

I'm not very familiar with Next.js or Webpack, but I seem to remember that some versions don't recognize ES Modules, so you can just import the UMD flavor in the /dist/ directory:

// old (ES Module):
import { ScrollTrigger } from "gsap/ScrollTrigger";

// new (UMD):
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";

Basically just put "/dist/" after the "gsap" for all the imports. 

 

28 minutes ago, dotsinspace said:

found out the issue..Gsap is using position: fixed with transform..

That would have nothing to do with the errors about imports/exports. And if your pinned element is inside a container that has a transform applied, you can just set pinType: "transform" to have it use transforms instead. Again, you'll have a much, much better chance of getting good answers here if you provide a minimal demo that clearly illustrates the problem. 

 

Good luck. 👍

Link to comment
Share on other sites

now after all this i got some success..but problem is that card not stacking properly.

Example: https://imgur.com/a/VzZCGTp

And this is the code which i am trying to opt. 

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

 

Now elements are pinned permanently using end: max, now as you can see in video i want to unpin all move all stackcards to the up as user scroll down. now they pinned permanently.

Link to comment
Share on other sites

Hi @dotsinspace. It doesn't really help if you provide one of the GreenSock CodePens that works perfectly, and then a video or screenshot of your implementation that isn't working properly. You've been asked at least 6 times now for a minimal demo that clearly illustrates the problem. I'm just not sure what else we can do here to help without seeing that. We need to see your actual code in context, in the browser (like in a CodeSandbox, CodePen, or Stackblitz). And in the most minimal way possible (no need to include your whole project - just a few simple colored <div> elements is fine). If you'd like more help, please provide one of those. 

 

You said you're using Next.js, so here is a starter template that you can fork on Stackblitz 

https://stackblitz.com/edit/nextjs-5cm4qn?file=pages%2Findex.js

Link to comment
Share on other sites

  • 5 months later...

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