Hi!
I've been struggling with a flash of unstyled content "FOUC" issue my entire day, testing various solutions I found online, but none seemed to work for me. The issue is especially visible when using CSS transitions, as the components will be visible without any styles and then transition to their CSS style.
This is only visible when building for production using next build and then next start. In development mode, using next, there is no FOUC issue.
Minimal example:
// next.config.js
const withSass = require('@zeit/next-sass');
module.exports = withSass();
// scss/style.scss
body {
background-color: red;
transition: 2s all ease;
}
// pages/index.js
import React from "react";
import "../scss/style.scss";
const Home = () => (
<div>Test</div>
);
export default Home;
GitHub repo: https://github.com/jesperlindstrom/next-sass-fouc/
Video of problem: https://drive.google.com/file/d/12yukgmgsuPKRs0TD2yYZK9F7fBC7oSkF/view?usp=sharing
What am I doing wrong? Thanks!
So... the issue turns out to be a browser bug, not related to Next or Webpack at all. Managed to replicate with ordinary CSS and HTML, where transitions are fired on load. The solution sounds very stupid but solves it: import an empty .js file in your
. I'm guesing it makes both the resources "blocking" and therefore waits for first render...If anyone has the same issue in Next.js, I added this to my _document.js:
<Head>
...
<script src="/static/chrome-fix.js" />
</Head>
...and put chrome-fix.js as an empty file in my /static.
More info: https://bugs.chromium.org/p/chromium/issues/detail?id=332189
Hi,
I'm still getting this problem, could you share an example (a simple repo) of your fix?
Adding a render blocking script like @jesperlindstrom suggested didn't work for me, but I imagine it could help in some cases.
The fix that I applied was adding a class to an html element that wrapped all of my components when component did mount. For example:
class WrapperComponent extends React.Component {
componentDidMount() {
this.layoutWrap.classList.add('enable-transitions');
}
render() {
return (
<div ref={(el) => this.layoutWrap = el}>
{this.props.children}
</div>
)
}
}
ComponentDidMount will only run on a client side render so the class 'enable-transitions` won't be added until page render. This allows you to update your css from something like:
a {
transition: .3s ease;
}
to something like:
.enable-transitions {
a {
transition: .3s ease;
}
}
You only need to remove the transition attribute of the style, to be in the .enable-transitions style block.
This is definitely gross work around, but it solves the problem.
Faced similar issue. Implementing a similar logic provided by @mitch-rickman in _app.js can actually solve for all the pages.
Most helpful comment
So... the issue turns out to be a browser bug, not related to Next or Webpack at all. Managed to replicate with ordinary CSS and HTML, where transitions are fired on load. The solution sounds very stupid but solves it: import an empty .js file in your
. I'm guesing it makes both the resources "blocking" and therefore waits for first render...If anyone has the same issue in Next.js, I added this to my _document.js:
...and put
chrome-fix.jsas an empty file in my /static.More info: https://bugs.chromium.org/p/chromium/issues/detail?id=332189