trackpad Posted March 29, 2023 Share Posted March 29, 2023 Sorry this project is too nascent to be published anywhere, so I am fishing for some more general guidance or advice, especially from anyone working in the contact of a React / Next.js implementation, as I suspect it is related to how things mount or are applied on the page transition of the parent, Layout.jsx. I 100% understand this isn't ideal, the not sharing of code or offering an example you can inspect, and I will do that if I don't give up on the idea before I get a test site up. I also really don't expect a solution, but as I am soon pulling my last hair out I thought I would show you the issue, explain what I've tried, and see if you can suggest anything else based on your past experiences. This is a screen recording that details the issue. https://www.icloud.com/sharedalbum/#B1253qWtHytDIK;B919597C-1871-4978-9E3A-5B9497D7626C The difficult part is it's not repeatable. Sometimes the ficker happens, sometimes it doesn't. I have tried a ton of different things in terms of restructuring the component, abstract different parts, applying delays, and CSS in JSX to set opacity to zero... I have also tried applying all the applicable will-change properties, and applied these to my h2 font-kerning: none; -webkit-text-rendering: optimizeSpeed; text-rendering: optimizeSpeed; -webkit-transform: translateZ(0); transform: translateZ(0); So I am happy to answer more questions, and again, I know it's not ideal... I tried to migrate this to codesandbox but I had so many issues after spending 30 minutes with it I had to cut my losses and throw a Hail Mary here. Key components are AnimatedHeader.jsx and useSplitText.js import React, { useEffect } from "react"; import useSplitText from "../hooks/useSplitText"; import { gsap } from "gsap"; const AnimatedHeader = ({ headline }) => { const [isSplitTextLoaded, SplitText] = useSplitText(); useEffect(() => { if (isSplitTextLoaded) { const childSplit = new SplitText("h2", { type: "words", wordsClass: "split-child", }); const parentSplit = new SplitText("h2", { type: "words", wordsClass: "split-parent", }); gsap.from(childSplit.words, { duration: 1.25, delay: 0.3, autoAlpha: 0, yPercent: 50, ease: "back.out(1.2)", stagger: 0.03, }); } }, [isSplitTextLoaded]); return ( <> <h2 className="will-change-transform split-parent block overflow-hidden pb-2 text-6xl text-stone-700"> {headline} </h2> <style jsx>{` .split-parent, split-child { will-change: opacity, transform; } `}</style> </> ); }; export default AnimatedHeader; import { useState, useEffect } from 'react'; import { gsap } from "gsap"; let SplitText; const useSplitText = () => { const [isLoaded, setIsLoaded] = useState(false); useEffect(() => { const loadSplitText = async () => { SplitText = (await import('../src/scripts/SplitText.min.js')).default; gsap.registerPlugin(SplitText); setIsLoaded(true); }; if (!SplitText) { loadSplitText(); } else { setIsLoaded(true); } }, []); return [isLoaded, SplitText]; }; export default useSplitText; <AnimatedHeader/> is then imported and placed on individual pages as needed. Link to comment Share on other sites More sharing options...
Solution elegantseagulls Posted March 29, 2023 Solution Share Posted March 29, 2023 Looks like maybe fouc to me? You'll want to set your initial css property to visibility: hidden; Better details here: 1 Link to comment Share on other sites More sharing options...
trackpad Posted March 30, 2023 Author Share Posted March 30, 2023 Thank you, @elegantseagulls ...setting visibility in tailwind seemed to present a problem with the cascade, or with autoAlpha anyway... setting it just kept the headers invisible. But I want to mark your suggestion as a solution because I think that is the answer in most other cases. And after seeing the example you linked to and looking at others, it occurred to me that fromTo might be the correct approach? So I modified my code to use that... gsap.fromTo( childSplit.words, // From properties { autoAlpha: 0, yPercent: 100, }, // To properties { duration: 0.6, autoAlpha: 1, yPercent: 0, ease: "back.out(1.2)", stagger: 0.04, } ); ...and I *think* it's fixed Thanks for the nudge! 1 Link to comment Share on other sites More sharing options...
trackpad Posted March 31, 2023 Author Share Posted March 31, 2023 I posted maybe a bit prematurely. 😕 Funny story actually.. often I am guessing "issues" with GSAP get reported that are in fact attributable to a browser or OS being maxed out on memory or swap or compute resources. Here it was sort of the opposite. Meaning, the perception I had that my issue had been fixed was probably a result of having a bunch of tabs open for a long time, and the browser dropping those errant frames in an effort to keep up. Restarting my browser actually exposed the problem had ...not been fixed. So I am looking for a way to make use of autoAlpha and trying to understand the cascade of CSS in the context of this next.js app, and where/how to set the class in such a way that GSAP can unset it with autoAlpha. Right now everything I am doing just results in the headline staying invisible. I've tried setting the style in a JSX <style> block just below the component and tried adding it to the stylesheet. Also tried applying via tailwind directly to the h2 element via invisible Any other ideas? 🙏 Link to comment Share on other sites More sharing options...
trackpad Posted March 31, 2023 Author Share Posted March 31, 2023 This is my updated AnimatedHeader component, having applied what I learned about useLayoutEffect, gsap's context/cleanup, and how to properly format/paste code into this forum. 🙄😬 The problem remains unchanged, so I'm still looking for the best way to set visibility:hidden in a way that gsap can access and undo. import React, { useLayoutEffect } from "react"; import useSplitText from "../hooks/useSplitText"; import { gsap } from "gsap"; const AnimatedHeader = ({ headline }) => { const [isSplitTextLoaded, SplitText] = useSplitText(); useLayoutEffect(() => { let ctx = gsap.context(() => { // all your GSAP animation code here if (isSplitTextLoaded) { const childSplit = new SplitText("h2", { type: "words", wordsClass: "split-child", }); const parentSplit = new SplitText("h2", { type: "words", wordsClass: "split-parent", }); gsap.fromTo( childSplit.words, // From properties { yPercent: 100, autoAlpha: 0, }, // To properties { duration: 1, delay: 0.2, autoAlpha: 1, yPercent: 0, ease: "back.out(1.2)", stagger: 0.06, } ); } }); return () => ctx.revert(); // <- cleanup! }, [isSplitTextLoaded]); return ( <> <h2 className="will-change-transform split-parent block overflow-hidden pb-2 text-4xl lg:text-6xl text-stone-700 font-playfair"> {headline} </h2> <style jsx>{` .split-parent { will-change: opacity, transform; } `}</style> </> ); }; export default AnimatedHeader; Link to comment Share on other sites More sharing options...
trackpad Posted March 31, 2023 Author Share Posted March 31, 2023 Sorry to be erratic or overly confident in what look like solutions, but I always feel it's better to followup quickly so no one wastes time or energy trying to help with something that might be solved? TLDR; if you're using Next.js or react – READ THIS, and try using useLayoutEffect even though React world would like you to use useEffect for most things for whatever reason... try both when you're having issues. In the above example I forgot to work on the imported hook. Simply changing useEffect to useLayoutEffect in this file seems to have fixed the issue for me. No more momentary flicker, and headlines are gliding in. So this is solving the FOUC issue for me in a way ...albeit without use of (or my successful application of ) visibility:hidden in CSS. It just works. I think. Restarted my browser a few times and can confirm the problem returns as I toggle back to useEffect on this imported hook. Would still like to know why I can't get autoAlpha to dismiss my visibility:hidden property. But I'll save that for another thread when the issue comes up again and feels more urgent. 3 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now