Jump to content
Search Community

Warning: Extra attributes from the server: style

cdedreuille test
Moderator Tag

Recommended Posts

Why would an empty style tag cause a bug? ScrollTrigger has to set inline styles temporarily during refresh() in order to ensure things are measured correctly and then it removes them of course. I’m baffled as to why that would cause any problems for you. I think it also sets scroll-behavior to make sure it’s not “smooth” which would break things.

Link to comment
Share on other sites

I believe this is due to the new server components structure in Nextjs 13. Our code is working fine but this warning is really annoying.

I’m also using Framer Motion who add and remove inline style as well but when styles are empty it doesn’t leave an empty style tag and no warning.

I’m using a basic scroll trigger animation and no other plugins.

is there a way to make sure style disappear if there’s no style applied to the body?

  • Like 1
Link to comment
Share on other sites

Just an idea?

 

From the docs - 

Advanced: listening for refresh/refreshInit events

ScrollTrigger will perform a "refreshInit" event immediately BEFORE refreshing all of the ScrollTriggers on the page, and then a "refresh" event immediately AFTER it's done. You can add a listener accordingly to call a function of your choice:



So maybe you could do something like this?

ScrollTrigger.addEventListener("refresh", function() {
  if(document.body.getAttribute('style') === '') {
    document.body.removeAttribute('style')
  }
});

 

Link to comment
Share on other sites

  • 2 weeks later...
  • 1 month later...
  • 1 month later...

  

On 2/3/2023 at 6:49 AM, chacrasoftware said:

run into similar issue using the app directory in NextJS 13. I'm using ScrollTrigger and ScrollSmoother plugin and managed to fix it by moving the gsap.registerPlugin(ScrollTrigger, ScrollSmoother) inside of useEffectuseIsomorphicLayoutEffect hook.

 

hope this helps

 

Thanks for sharing the solution, I was getting irritated solving it. You made my day :)

  • Like 1
Link to comment
Share on other sites

  • 4 months later...
On 2/2/2023 at 10:19 PM, chacrasoftware said:

run into similar issue using the app directory in NextJS 13. I'm using ScrollTrigger and ScrollSmoother plugin and managed to fix it by moving the gsap.registerPlugin(ScrollTrigger, ScrollSmoother) inside of useEffectuseIsomorphicLayoutEffect hook.

 

hope this helps

Hi! Facing the same problem here using Next App router. Are there any benefits of the ssr lost if using this solution?
Normally you don't run any gsap on the server, but just in case.

Link to comment
Share on other sites

23 hours ago, Joyboy said:

Are there any benefits of the ssr lost if using this solution?

As far as I can tell, nope.

 

One thing you can do in order to be 100% safe is to create a super simple client component that returns null and registers the plugins in the Isomorphic Effect:

 

import RegisterComponent from "/route-to-components/RegisterComponent.js";

const Home = () => {
  return (
    <div>
    <RegisterComponent />
    /* Rest of your content here */
    </div>
  );
};

Then in that particular file:

"use client";

import gsap from "gsap";
import { ScrollTrigger } from "gsap/dist/ScrollTrigger";
import { ScrollSmoother } from "gsap/dist/ScrollSmoother";

import useIsmorphicLayoutEffect from "/route-to-file/ismorphicLayoutEffect";

const RegisterComponent = () => {
  useIsmorphicLayoutEffect(() => {
    gsap.registerPlugin(ScrollTrigger, ScrollSmoother);
  }, []);
  return null;
};

export default RegisterComponent;

That is valid JS and React syntax so it should run just on the client without hurting any other SSR capability from a regular react component.

 

Finally as far as I know, client components and pages in Next are still rendered in the server first and then hydrated on the client-side:

https://nextjs.org/docs/app/building-your-application/rendering/client-components#how-are-client-components-rendered

 

When using GSAP your JS code will always have to work in the client side, no way around it since there is no point on running GSAP on the server, plus there is no request animation frame there as well and finally given the fact that GSAP animates UI elements and relies (with good reason, which is something React team members actually recommend) on the useEffect/useLayoutEffect hooks to do so, there is not a lot of reason for going through all that hassle if, at the end you'll end up with a bunch of client components either way. This is based in the recommendations made by the Next documentation actually:

https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#when-to-use-server-and-client-components

 

Hopefully this helps.

Happy Tweening!

  • Like 1
Link to comment
Share on other sites

  • 9 months later...

I'm using remix + vite setup. 

Registering ScrollTrigger in useEffect gives weird errors. I don't really understand what this error is. 
image.png.9980d7071ed18058fc8c0fe028e7fc39.png
This error is gone and scrolltrigger works if I register the ScrollTrigger first thing in my useGsap hook
BUT, if I do this, the numeric scrub values stop having any effect, they behave as if that value was scrub=true.

And then if I do outside my react component

if (typeof document !== "undefined") {
gsap.registerPlugin(MotionPathPlugin, useGSAP, ScrollTrigger);
}

Everything works, but that annoying empty style tag warning pops up. 🤦🏻 


Came here from this thread: 


 

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

Hi,

 

I just created a simple demo using the approach I mentioned in a previous post, creating a different client component that registers the plugins and creates the ScrollSmoother instance using a useLayoutEffect. Something like this:

"use client";

import { useLayoutEffect } from "react";
import gsap from "gsap-trial";
import { ScrollTrigger } from "gsap-trial/dist/ScrollTrigger";
import { ScrollSmoother } from "gsap-trial/dist/ScrollSmoother";
import { useGSAP } from "@gsap/react";

const RegisterGSAP = () => {
  useLayoutEffect(() => {
    gsap.registerPlugin(
      useGSAP,
      ScrollTrigger,
      ScrollSmoother,
    );
    ScrollSmoother.create({
      smooth: 1,
      effects: true,
    });
  }, []);

  return null;
};

export default RegisterGSAP;

Used like this on the layout.js/jsx/tsx file:

import { Inter } from "next/font/google";

import "./globals.css";
import RegisterGSAP from "../components/RegisterGSAP";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout ({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <RegisterGSAP />
        <div id="smooth-wrapper">
          <div id="smooth-content">
            {children}
          </div>
        </div>
      </body>
    </html>
  );
}

I made a small demo in Stackblitz showing the general structure of the project:

https://stackblitz.com/edit/stackblitz-starters-xt1ucd?file=app%2Flayout.tsx,components%2FRegisterGSAP.tsx

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

Thanks for the above @Rodrigo.

I'm using remix+vite.
I tried doing this in my project, a pretty basic version.
 

useGSAP(() => {
ScrollTrigger.create({
trigger: ".hero__description",
start: "top top",
end: "top -=1000px",
animation: gsap.to("body", { y: 1000 }),
scrub: true,
});
});


it works if I put the above logic in a useEffect.
For some reason I get the error (screenshot shared earlier) if I put the scroll trigger logic within the useGsap hook. 

I'll try to create a demo when I find some time. 
Thanks. :)

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