Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flash of unstyled content (FOUC) #5188

Open
gslopez opened this issue Oct 29, 2023 · 25 comments · May be fixed by #5228
Open

Flash of unstyled content (FOUC) #5188

gslopez opened this issue Oct 29, 2023 · 25 comments · May be fixed by #5228
Assignees
Labels
Type: Bug Issue contains a defect related to a specific component. Type: Performance Issue is performance or optimization related
Milestone

Comments

@gslopez
Copy link

gslopez commented Oct 29, 2023

Describe the bug

When using built in PR theme seeing a flash of un-styled content: https://en.wikipedia.org/wiki/Flash_of_unstyled_content

I have this super simple code

import React, {useState} from 'react';
import {TabMenu} from 'primereact/tabmenu';
import {MenuItem} from 'primereact/menuitem';


type NavbarProps = {
    onPageSelected?: (page: string) => void,
    menuItems?: MenuItem[],
}

export const Navbar = ({menuItems, onPageSelected}: NavbarProps) => {
    const [activeIndex, setActiveIndex] = useState(0)

    return (
        <TabMenu
            activeIndex={activeIndex}
            model={
                menuItems
            }
            onTabChange={(e) => {
                setActiveIndex(e.index);
                onPageSelected?.(e.value.id as string)
            }}
        />
    )
}

When the page first loads, it looks like this first for like 0.5 seconds

Screenshot 2023-10-29 at 3 24 56 PM

and then it changes to how it should really look

Screenshot 2023-10-29 at 3 24 47 PM

After some debugging I found out it is because when the component is loaded, it loads this global style
Screenshot 2023-10-29 at 3 27 42 PM

https://github.com/primefaces/primereact/blob/master/components/lib/tabmenu/TabMenuBase.js#L79
https://github.com/primefaces/primereact/blob/master/components/lib/componentbase/ComponentBase.js#L664

I recorded this video with the issue on the codesandbox i created

primereact.issue.mov

I would expect either

  1. The component should be auto-sufficient (i.e it looks properly on first load)
  2. To have a way to import the components css globally directly, next to the theme and min imports (something like import "primereact/components/tabmenu.css

Reproducer

https://codesandbox.io/s/primereact-test-forked-xsr6gj?file=/src/index.js

PrimeReact version

10.0.7

React version

18.x

Language

TypeScript

Build / Runtime

Create React App (CRA)

Browser(s)

No response

Steps to reproduce the behavior

No response

Expected behavior

No response

@gslopez gslopez added the Status: Needs Triage Issue will be reviewed by Core Team and a relevant label will be added as soon as possible label Oct 29, 2023
@melloware melloware added Type: Bug Issue contains a defect related to a specific component. and removed Status: Needs Triage Issue will be reviewed by Core Team and a relevant label will be added as soon as possible labels Oct 30, 2023
@melloware
Copy link
Member

melloware commented Oct 30, 2023

I agree I have seen this same flash flicker when it renders.

This is known as FOUC https://en.wikipedia.org/wiki/Flash_of_unstyled_content and maybe all those base styles need to be extracted into a primereact.css like you said so if we want we can include it in the page and not need each component to dynamically add the CSS to the HEAD

@melloware melloware changed the title Tabmenu: Loading global styles after page is loaded looks weird Tabmenu: Flash of unstyled content (FOUC) Oct 31, 2023
@melloware
Copy link
Member

@gslopez check this out can you try this: https://codesandbox.io/s/primereact-test-forked-9cl6y8?file=/src/styles.css

I merged all of the base styles into a single CSS file to load. If this meets your needs I think I can propose something clever.

melloware added a commit to melloware/primereact that referenced this issue Nov 2, 2023
@melloware melloware linked a pull request Nov 2, 2023 that will close this issue
3 tasks
@melloware melloware added this to the 10.0.10 milestone Nov 2, 2023
@melloware melloware assigned melloware and unassigned mertsincan and habubey Nov 2, 2023
melloware added a commit to melloware/primereact that referenced this issue Nov 3, 2023
@melloware
Copy link
Member

Updated with more complete version of the final CSS: https://codesandbox.io/s/primereact-test-forked-9cl6y8?file=/src/styles.css

@gslopez
Copy link
Author

gslopez commented Nov 3, 2023

hey @melloware! Thanks for the quick answer. Yeah, if I add import "./styles.css"; to that codesandbox it seems to be working fine. I think this is good enough for my current project 🙏

@alaordev
Copy link

alaordev commented Nov 9, 2023

@melloware any date prediction of 10.0.10 release? Facing the same issue here

@melloware
Copy link
Member

This fix has not been included in 10.0.10 yet as PrimeTek is still discussing my fix. For now you can use the CSS in the reproducer above to temporarily fix your issue.

@melloware melloware changed the title Tabmenu: Flash of unstyled content (FOUC) Flash of unstyled content (FOUC) Nov 10, 2023
@cagataycivici cagataycivici modified the milestones: 10.1.0, 10.2.0 Nov 20, 2023
@melloware
Copy link
Member

NextJS 14 reproducer: https://stackblitz.com/edit/stackblitz-starters-mqapwn?file=app%2Fglobals.css,app%2Flayout.tsx

@melloware melloware added the Type: Performance Issue is performance or optimization related label Nov 25, 2023
@mertsincan mertsincan modified the milestones: 10.2.0, 10.3.0 Nov 27, 2023
@axlerk
Copy link
Contributor

axlerk commented Feb 1, 2024

Facing the same issue while migrating to a major version 8 → 10 on my project. Any news here? It's look like a blocker for me

@melloware
Copy link
Member

You can use my workaround posted above

@lsegal
Copy link

lsegal commented Feb 4, 2024

You can use my workaround posted above

@melloware do you mean this?

Updated with more complete version of the final CSS: https://codesandbox.io/s/primereact-test-forked-9cl6y8?file=/src/styles.css

This codesandbox still shows a FOUC on first load. It's a little less noticeable but it still occurs. A little difficult to show with Chrome Inspector (it limits how big the Visual Preview window can be) but the following shows the list elements along with the final rendered content 1ms later:

image
image

@melloware
Copy link
Member

Yes it doesn't eliminate it it just makes it less jarring by preloading CSS.

@axlerk
Copy link
Contributor

axlerk commented Mar 19, 2024

Is it possible to somehow escalate this issue? Add more likes or idk :) Looks important.

@melloware
Copy link
Member

@axlerk PrimeTek is aware of this issue its on their radar.

@emirhancopoglu
Copy link

any news?

@thingersoft
Copy link

any news?

+1

@cdllc
Copy link

cdllc commented May 19, 2024

+another

@emirhancopoglu
Copy link

+++

@starlocater
Copy link

++++

@axlerk
Copy link
Contributor

axlerk commented Jun 3, 2024

@melloware could you update the workaround for version 10.6.6 please? Until we have a solution

@melloware
Copy link
Member

@axlerk i assume you means some styles are missing from my giant CSS file?

@acho1833
Copy link

acho1833 commented Jun 8, 2024

Now I get what @melloware is saying now, PrimeReact adds the styles 'after' the component have already been rendered.
See the left side of the screenshot and you'll notice that 'base', 'global', 'splitbutton', are being added dynamically. On the right side of the screen, you don't and that's why it's showing FOUC.

image

I think I can come with decent 'workaround' solution without putting those css somewhere. My idea is the following. Please let me know if my logic can be improved or flawed.

  1. Make the body tag to be display:none in the Root Layout component. Something like
<body style={{display: "none"}}>
  1. Add a script tag, that checks for added styles with the attribute 'data-primereact-style-id'. Check that at least 3 of them exists (Imagine those are 'base', 'global', 'common') and maybe add another 50ms and then change the body style back to 'block'/'flex'/or whatever...

Hopefully this will work as temporary workaround...

@melloware
Copy link
Member

@acho1833 yes you understand the issue now. PrimeTek I think is working on a long term solution after their next big refactor.

@acho1833
Copy link

acho1833 commented Jun 8, 2024

My theory seems to work and I think it's good to go now. To me, this is enough until the fix and looks perfect to me.


export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <head>
        <style
          dangerouslySetInnerHTML={{
            __html: `
              body {
                display: none;
              }
            `,
          }}
        />
        <script
          dangerouslySetInnerHTML={{
            __html: `
                document.addEventListener('DOMContentLoaded', function() {
                    const intervalId = setInterval(() => {
                        const elements = document.querySelectorAll('head > style[data-primereact-style-id]');
                        if (elements.length >= 3) {
                            document.body.style.display = 'block';
                            clearInterval(intervalId);
                        }
                    }, 50);
                });
            `,
          }}
        />
      </head>
      <body className={inter.className}>
        <PrimeReactProvider>{children}</PrimeReactProvider>
      </body>
    </html>
  );
}

@melloware looking forward for next release. Is that real soon? know any rough ETA?

@melloware
Copy link
Member

I don't work for PrimeTek so I don't know the internal details of their schedule or roadmap.

@Saul-Sosa-Diaz
Copy link

I have found a solution for nextjs in another issue that directs to this nextjs page, at least this worked for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Bug Issue contains a defect related to a specific component. Type: Performance Issue is performance or optimization related
Projects
None yet
Development

Successfully merging a pull request may close this issue.