next.js
next.js copied to clipboard
Verify CSS import ordering
A user on twitter reported that Next.js may not order CSS imports from JS correctly. We need to investigate and fix this!
https://twitter.com/samselikoff/status/1299032241100787712
this is still happening to me
@Timer I tried with latest versions including the v9.5.4-canary.5
the issue still there, I am importing global.scss
from _app.js
and then I have different scss module files. with yarn dev
the order is correct, but when doing yarn build && yarn start
the order gets changed, so for example, the global bootstrap classes override module classes as is loaded after
could be related to https://github.com/vercel/next.js/issues/16723
Hey! I'm having trouble with that too. See my repo for my code and Stackoverflow for my problem.
same here
Nextjs is one of the greatest things in JS landscape, thanks for great work!
Also this bug is killing me, we have a pretty big app with millions of users and update from 9.0.3 to 9.5.5 broke our app in so many places, I cant even imagine how to hotfix this...
Please, fix this 🙏
Did anyone find any solution for this?
i create a new css file:style.css
and manual import css like the code below, replace the css import in _app.tsx
before.
`@import './node_modules/@hackplan/uui/lib/index.css'; @import './node_modules/react-weui/build/packages/react-weui.css'; @import './node_modules/react-image-gallery/styles/css/image-gallery.css';
@import './static/css/app.css';
.style { color: aliceblue; }`
then add import '../style.css'
in _app.tsx
Thanks, @sunoj but it did not work out for us.
same here
next@10 react@17
I believe I have this issue as well
Is there anything we can do to help resolve this issue?
I can confirm this bug exists at 10.0.3 also! Reproduction is here: #19055 Just can't use Next.js due to such annoying bug: I am using CSS Modules so can't order styles manually and only one possible fix is to add "!important", but for some projects this is a really inconvenient, for some - just impossible.
My own example:
same here, huge issue for us
I've seen some improvement when going from 10.0.3
-> 10.0.5
, but there remain cases where this bug occurs.
I still have the same issue with 10.0.5. Order is still broken
Also a problem for me on 10.0.5
. Temp fixed the issue with throwing in !important
everywhere the ordering was broken
Same issue version 10.0.5. How to disable code-splitting?
For me, the problem was I had a global wrapper component <Layout /> imported on _app.js. It contained a navbar and a footer component and rendered the children in the middle. It seems there is not a CSS order problem, but a CSS class duplication problem, because while inspecting the build output I was able to see some classes from the global chunk being redeclared in the page chunk, and since the page chunk is added to the HTML after the global one, it caused some styles to be overwritten. My solution, for now, is to avoid importing any component inside _app.js, instead, I added my <Layout /> wrapper to every page. Not so DRY, but it is working now...
@edgardz your case seems to be the same we're discussing here https://github.com/vercel/next.js/issues/20203. In our particular scenario, we're experiencing both: the duplication occurs by using components with style inside _app.js (and thus there's a style chunk created for the "_app.js"), and the chunk responsible for the "_app.js" style is ordered after the page chunk, causing the rewrite in different classes (global ones), like the comment from @santiagoRebella https://github.com/vercel/next.js/issues/16630#issuecomment-688382667
@edgardz your case seems to be the same we're discussing here #20203. In our particular scenario, we're experiencing both: the duplication occurs by using components with style inside _app.js (and thus there's a style chunk created for the "_app.js"), and the chunk responsible for the "_app.js" style is ordered after the page chunk, causing the rewrite in different classes (global ones), like the comment from @santiagoRebella #16630 (comment)
Yup. I just checked and my solution is making the <Layout /> component to be re-rendered at each navigation as described in the other issue. So now I changed it a bit, instead of adding the Layout to the render function, I just import it at each page. It is a workaround... Hope they fix this soon.
We are experiencing the same problem. Did anybody manage to solve this?
+1 on this thread. When will this be fixed?
+1
+1
I had a similar issue using postcss, and it was an issue occurring in prod and dev environments.
If I had a nested rule, the nested rule was created before the actual class rule, and with that, the nested rule was overwritten by the class one, and it also happened with media-queries.
so if I had a css file like:
.someClass {
background-color: red;
&Blue {
background-color: blue;
}
}
My css result was:
.someClassBlue {
background-color: blue;
}
.someClass {
background-color: red;
}
I was using Next 10.0.7 and the plugin that was causing an issue for me was: postcss-nested
.
I Changed postcss-nested
for precss
and it solved my issue, so if you are experiencing some weird-ass css ordering with postcss you can try removing some plugins and see if things get to work.
If you are using postcss, you can also add postcss-sorting
and try fixing it by force.
extract import to css works in webpack4
@import '~normalize.css/normalize.css';
@import '~@blueprintjs/icons/lib/css/blueprint-icons.css';
@import '~@blueprintjs/core/lib/css/blueprint.css';
@import '~@blueprintjs/select/lib/css/blueprint-select.css';
@import '~@blueprintjs/datetime/lib/css/blueprint-datetime.css';
@import '~@blueprintjs/popover2/lib/css/blueprint-popover2.css';
@import '~@blueprintjs/table/lib/css/table.css';
@import '~tailwindcss/tailwind.css';
@import '~nprogress/nprogress.css';
If enable webpack5 feature, this will not works.
Has this been fixed?
any update?
I'm having the same issue. This is the first project I work using NextJS and this is making it impossible to proceed. I don't know if this is an issue with a specific configuration (even though my project is really barebones now) or if this issue is affecting everyone.
I would assume that is not affecting everyone, otherwise it would be impossible for others to complete any project, so I will try to start a new project and only import a global css and a module css and check the order with build
and export
.
If anyone has a solution for this please let me know, currently this is the only issue blocking me from using NextJS
Saaaame "next": "^11.0.1", "react": "^17.0.2",
Only hotfix i found out is to throw an !important
on every css module class that's broken.
Same here. Is there any workaround who doesn't use !important ?
The only clean workaround\solution i found is:
- Do not override previous CSS rules
- Use conditional styles like,
row ? Style.flexRow : Style.flexColumn
in component itself. ("row" is a prop)
Works well if you writing your components from ground up. For example:
const Flex = ({ className, row, ...rest}) => {
...
const style = classNames(Style.flex, row ? Style.row : Style:column) //classNames is a helper function.
return <div className={style} {...rest}/>
}
Use !important
as a last resort.
The only clean workaround\solution i found is:
1. Do not override previous CSS rules 2. Use conditional styles like, `row ? Style.flexRow : Style.flexColumn` in component itself. ("row" is a prop)
Works well if you writing your components from ground up. For example:
const Flex = ({ className, row, ...rest}) => { ... const style = classNames(Style.flex, row ? Style.row : Style:column) //classNames is a helper function. return <div className={style} {...rest}/> }
Use
!important
as a last resort.
Thanks for your reply.
Very often we have to overload styles (with a css reset for example or a third party library) and it is essential to respect the loading order.
The only clean workaround\solution i found is:
1. Do not override previous CSS rules 2. Use conditional styles like, `row ? Style.flexRow : Style.flexColumn` in component itself. ("row" is a prop)
Works well if you writing your components from ground up. For example:
const Flex = ({ className, row, ...rest}) => { ... const style = classNames(Style.flex, row ? Style.row : Style:column) //classNames is a helper function. return <div className={style} {...rest}/> }
Use
!important
as a last resort.Thanks for your reply.
Very often we have to overload styles (with a css reset for example or a third party library) and it is essential to respect the loading order.
@clementbiron what third party libraries have you used that actually work/fix this problem? And also... how do you make a css reset? Does it work with this threads problem? :D
The only clean workaround\solution i found is:
1. Do not override previous CSS rules 2. Use conditional styles like, `row ? Style.flexRow : Style.flexColumn` in component itself. ("row" is a prop)
Works well if you writing your components from ground up. For example:
const Flex = ({ className, row, ...rest}) => { ... const style = classNames(Style.flex, row ? Style.row : Style:column) //classNames is a helper function. return <div className={style} {...rest}/> }
Use
!important
as a last resort.Thanks for your reply. Very often we have to overload styles (with a css reset for example or a third party library) and it is essential to respect the loading order.
@clementbiron what third party libraries have you used that actually work/fix this problem? And also... how do you make a css reset? Does it work with this threads problem? :D
the only workaround i know is to use !important
I solved it,inspired by this: https://github.com/SolidZORO/mkn/blob/master/src/pages/_app.tsx Disable ssr transition,add these lines code:
In _document.tsx:
export const DISABLE_SSR_TRANSITION = "disable-SSR-transition";
...
<body>
<Main />
<NextScript />
<style
id={DISABLE_SSR_TRANSITION}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: "*, *::before, *::after { transition: none !important; }",
}}
/>
</body>
In _app.tsx:
import { DISABLE_SSR_TRANSITION } from "./_document";
export const isServer = () => typeof window === "undefined";
function MyApp({ Component, pageProps }: AppProps) {
useEffect(() => {
// avoid CSS animation flashing
if (!isServer()) {
const disableTransitionDom = document.getElementById(DISABLE_SSR_TRANSITION);
if (disableTransitionDom) disableTransitionDom.remove();
}
}, []);
return <Component {...pageProps} />;
}
export default MyApp;
Thanks to @SolidZORO
The simplest solution is to wrap your component styles in the scss with #__next { your styles }
, no need to complex refactors
@santiagoRebella Wow, Wrapping my CSS classes into one component style really fixed my case! And yes, for now. Thanks!
Wrapping my scss file with #__next didn't help, any news regarding this issue?
I'm using 11.1.0
and still have this issue.
my code is like this:
import css from "./file.module.scss";
<div className={css["felan"]}>
<p> has no class </p>
</div>
the div has correct css order: file.module.scss > global.scss
but p doesn't: global.scss > file.module.scss
i'm using nextjs12
and used bootstrap/dist/css/bootstrap.min.css
in my application so we i want to overwrite some css from bootstrap
it is not working in dev
everything works fine but in prod
having issue
@Timer having that same issue. We were using [email protected] and it wasn't the case but I updated [email protected] after that we face with this issue. That issue is only works in production, dev is fine. Could you please check that?
@timneutkens @sokra have you been able to investigate a bit this issue and know where this might come from?
We have a quite similar CSS ordering problem on Docusaurus with Webpack 5 and a single CSS file output: https://github.com/facebook/docusaurus/pull/6227
What I see is that:
- for static require/imports, CSS order seems preserved (ie same order as imports)
- for dynamic imports (like dynamic route components, each page using statically imported CSS modules) the CSS is inserted last and order becomes less predictable.
The simplest solution is to wrap your component styles in the scss with
#__next { your styles }
, no need to complex refactors
@santiagoRebella @penguin-io Care to give more insight on this? Wrapping the class in the .scss? In the import?
Is this still on the radar @timneutkens? From what I've gathered researching in the past hour, any references to this issue is either
- closed as "resolved" despite many others claiming the issue still exists ( https://github.com/vercel/next.js/issues/10148, https://github.com/vercel/next-plugins/issues/399 )
- Removed from milestones, seemingly not added again (https://github.com/vercel/next.js/milestone/66, https://github.com/vercel/next.js/milestone/69)
And as others have also said, workarounds like !important
flags could only go so far, and a large refactor like say migrating to CSS in JS is not a single day task in a production application
Yes, @sokra is currently working on built-in CSS support in webpack which will solve this.
Regarding 2.
we no longer use milestones to track issues.
Am also facing the issue: https://github.com/vercel/next.js/issues/34264 Only in v12 in PRODUCTION. Works fine in v11
Any solutions other than using !important ?
@heylols for now i manage to work this by.
app.scss
in _app.tsx
then inside app.scss
import all th css in right order i m using nextjs 12
For Next 12, a version of this bug occurs with any css files imported in _app that begin with an @import
line. I have a reproduction at https://codesandbox.io/s/cold-cookies-23gxz?file=/pages/green.css:
There are two CSS files being included in the intended order in _app.js: red then green. In development, you see a green page. When you build the app with next build
and view the page yarn start -p 3001
the background changes to red because the order of CSS changes.
Expected behavior: the presence of @import
on the very first line of a CSS file should have no impact on the ordering of the CSS.
👉 Workaround: simply adding a comment or newline before the @import
in green.css or removing the line fixes the issue.
@visnup I can confirm that the workaround fixes that behaviour. Thank you so much! I think it would make sense to open an extra issue for that, since it only occurred after upgrading to Next.js 12.
I can also confirm @visnup's workaround in https://github.com/vercel/next.js/issues/16630#issuecomment-1037305875
I tried adding a comment before @import
in my CSS file, but Next just left this line somewhere in the middle of resulting CSS file. Then, I moved @import
to its own separate CSS file and imported it to my _app.tsx
after my main CSS. This way it magically works — styles are applied in the correct order. My next.js version is 12.1.0.
Waiting for a proper fix!
I can also confirm @visnup's workaround works.
In my case, I was using Ant Design, reset CSS, and my own global CSS. I was trying to achieve applying the reset CSS after the CSS of Ant Design, and the global CSS at the end.
A permanent solution would be nice.
Before the workaround _app.js file (works in dev, but not prod):
import "antd/dist/antd.min.css";
import "../styles/reset.css";
import "../styles/globals.css";
Before the workaround globals.css file:
@import url("https://fonts.googleapis.com/css2?family=Josefin+Sans&display=swap");
html
{
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
font-size: 62.5%;
font-family: "Josefin Sans", sans-serif;
}
After the workaround _app.js file:
import "antd/dist/antd.min.css";
import "../styles/globals.css";
After the workaround globals.css file:
@import url("../styles/reset.css");
@import url("https://fonts.googleapis.com/css2?family=Josefin+Sans&display=swap");
html
{
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
font-size: 62.5%;
font-family: "Josefin Sans", sans-serif;
}
For anyone looking for a robust, future-proof and portable solution: CSS Cascade Layers have been implemented in all major browsers
So it's only a matter of time until we can use this in production
Why does this matter? You can put CSS rules in layers and choose the order in which layers are applied.
A CSS rule at the top of your CSS file can now have a higher specificity than a CSS rule at the bottom (without using !important or change selectors: just put the rule in a layer)
This means that basically, you can make your CSS work despite the bundler outputting styles in a weird unexpected order

https://www.smashingmagazine.com/2022/01/introduction-css-cascade-layers/
I like this little video: https://twitter.com/bramus/status/1493330153681920001
It shows well that somehow the browser "sort your rules according to the layers, so if you use layers, the order of rules in the CSS files do not matter as much as before

This bug is preventing us from deploying an optimization to the _app
page that saves ~100kb per page load. This is frustrating, especially as we are trying to optimize our usage on Vercel to stay under our monthly bandwidth limit.
We are using SASS so it appears as though @visnup's fix doesn't work.
Hey @timneutkens, are there any news on the fix? This is a really annoying bug, and CSS layers aren't coming soon enough 😕
:( same here
Same here.
Next 12.2.0
React 18.2.0
I had a similar error with my header/footer styles being loaded before my global styles.
It was the result of adding an Error Boundary as described at https://nextjs.org/docs/advanced-features/error-handling
To use Error Boundaries for your Next.js application, you must create a class component
ErrorBoundary
and wrap theComponent
prop in thepages/_app.js
file.
My _app.js file now looked like this:
// _app.js
import ReactModal from 'react-modal';
import ErrorBoundary from '../components/misc/ErrorBoundary';
import '../path/to/global.css';
function MyApp({ Component, pageProps }) {
ReactModal.setAppElement('#__next');
return (
<ErrorBoundary>
<Component {...pageProps} />
</ErrorBoundary>
);
}
export default MyApp;
See the problem? Nope?
My ErrorBoundary
wraps the error message with a pretty page (including normal headers/footers).
For components, I always follow this pattern of imports:
- Import component dependencies first.
- Import local assets last (including CSS, images, etc.)
That pattern broke down here because global CSS isn't a local asset of the _app.js
; It's a global dependency and should be imported before any component.
By importing ErrorBoundary
before global.css
I was literally telling my app to load all my header/footer CSS (that is used both on the error page and normal pages) before the global CSS that my components depend on.
The fix was simple:
// _app.js
// Load global CSS before any component that depends on it.
import '../path/to/global.css';
import ReactModal from 'react-modal';
import ErrorBoundary from '../components/misc/ErrorBoundary';
function MyApp({ Component, pageProps }) {
ReactModal.setAppElement('#__next');
return (
<ErrorBoundary>
<Component {...pageProps} />
</ErrorBoundary>
);
}
export default MyApp;
The docs for Adding a Global Stylesheet only show a very basic _app.js
with only 1 import statement (the single CSS file).
I suspect this might be a docs issue instead of an actual bug.
- The Adding a Global Stylesheet docs page should be updated. https://github.com/vercel/next.js/pull/39889
- The Error Handling docs page should be updated. https://github.com/vercel/next.js/pull/39890