next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Verify CSS import ordering

Open Timer opened this issue 4 years ago • 62 comments

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

Timer avatar Aug 27 '20 19:08 Timer

this is still happening to me

santiagoRebella avatar Sep 04 '20 22:09 santiagoRebella

@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 Screen Shot 2020-09-07 at 12 06 56 PM Screen Shot 2020-09-07 at 12 07 10 PM Screen Shot 2020-09-07 at 12 08 46 PM

santiagoRebella avatar Sep 07 '20 15:09 santiagoRebella

Hey! I'm having trouble with that too. See my repo for my code and Stackoverflow for my problem.

Aichnerc avatar Sep 28 '20 06:09 Aichnerc

same here

sunoj avatar Oct 08 '20 15:10 sunoj

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 🙏

kenaku avatar Oct 13 '20 16:10 kenaku

Did anyone find any solution for this?

usamamashkoor avatar Oct 16 '20 23:10 usamamashkoor

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

sunoj avatar Oct 17 '20 05:10 sunoj

Thanks, @sunoj but it did not work out for us.

usamamashkoor avatar Oct 17 '20 14:10 usamamashkoor

same here

next@10 react@17

ghost avatar Nov 03 '20 18:11 ghost

I believe I have this issue as well

uthd-dev avatar Nov 30 '20 05:11 uthd-dev

Is there anything we can do to help resolve this issue?

klaemo avatar Dec 09 '20 08:12 klaemo

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:

2020-12-15_12-18-29

iksent avatar Dec 15 '20 07:12 iksent

same here, huge issue for us

newtoniumx3 avatar Dec 28 '20 18:12 newtoniumx3

I've seen some improvement when going from 10.0.3 -> 10.0.5, but there remain cases where this bug occurs.

klaemo avatar Jan 12 '21 14:01 klaemo

I still have the same issue with 10.0.5. Order is still broken

phbetbeze avatar Jan 12 '21 21:01 phbetbeze

Also a problem for me on 10.0.5. Temp fixed the issue with throwing in !important everywhere the ordering was broken

Gilbert09 avatar Jan 27 '21 13:01 Gilbert09

Same issue version 10.0.5. How to disable code-splitting?

omarabid avatar Jan 29 '21 23:01 omarabid

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 avatar Feb 01 '21 19:02 edgardz

@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

alexandre-marchina avatar Feb 01 '21 20:02 alexandre-marchina

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

edgardz avatar Feb 01 '21 20:02 edgardz

We are experiencing the same problem. Did anybody manage to solve this?

spaghettiguru avatar Feb 16 '21 13:02 spaghettiguru

+1 on this thread. When will this be fixed?

theivanfranco avatar Feb 19 '21 02:02 theivanfranco

+1

AlexandrKolesnikov avatar Feb 20 '21 19:02 AlexandrKolesnikov

+1

ViktorSoroka07 avatar Mar 16 '21 14:03 ViktorSoroka07

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.

Capeleto avatar Apr 05 '21 18:04 Capeleto

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.

wenerme avatar Apr 24 '21 17:04 wenerme

Has this been fixed?

Pranav2612000 avatar Jun 19 '21 10:06 Pranav2612000

any update?

yenicelik avatar Jun 20 '21 14:06 yenicelik

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

marcos-abreu avatar Jun 24 '21 20:06 marcos-abreu

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.

oaa97181 avatar Jun 28 '21 19:06 oaa97181

Same here. Is there any workaround who doesn't use !important ?

clementbiron avatar Jul 02 '21 09:07 clementbiron

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.

Hellaeh avatar Jul 02 '21 09:07 Hellaeh

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 avatar Jul 02 '21 09:07 clementbiron

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

oaa97181 avatar Jul 02 '21 14:07 oaa97181

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

clementbiron avatar Jul 07 '21 06:07 clementbiron

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

rumsky avatar Jul 07 '21 11:07 rumsky

The simplest solution is to wrap your component styles in the scss with #__next { your styles }, no need to complex refactors

santiagoRebella avatar Jul 07 '21 13:07 santiagoRebella

@santiagoRebella Wow, Wrapping my CSS classes into one component style really fixed my case! And yes, for now. Thanks!

pak-ferry avatar Jul 15 '21 09:07 pak-ferry

Wrapping my scss file with #__next didn't help, any news regarding this issue?

GalInvesting avatar Aug 22 '21 13:08 GalInvesting

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

ShahriarKh avatar Aug 31 '21 16:08 ShahriarKh

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

Kamleshpaul avatar Dec 27 '21 15:12 Kamleshpaul

@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?

EmirBoyaci avatar Jan 05 '22 13:01 EmirBoyaci

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

slorber avatar Jan 05 '22 15:01 slorber

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?

cgarrovillo avatar Jan 19 '22 17:01 cgarrovillo

Is this still on the radar @timneutkens? From what I've gathered researching in the past hour, any references to this issue is either

  1. 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 )
  2. 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

cgarrovillo avatar Jan 19 '22 19:01 cgarrovillo

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.

timneutkens avatar Jan 20 '22 10:01 timneutkens

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 avatar Feb 12 '22 12:02 heylols

@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

Kamleshpaul avatar Feb 12 '22 16:02 Kamleshpaul

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 avatar Feb 12 '22 16:02 visnup

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

michaelschufi avatar Feb 21 '22 14:02 michaelschufi

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!

maksbotan avatar Mar 05 '22 10:03 maksbotan

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;
}

onurcipe avatar Mar 23 '22 09:03 onurcipe

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

image

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

image

slorber avatar Mar 25 '22 13:03 slorber

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.

bscaspar avatar Jun 08 '22 21:06 bscaspar

Hey @timneutkens, are there any news on the fix? This is a really annoying bug, and CSS layers aren't coming soon enough 😕

riffbyte avatar Jul 22 '22 09:07 riffbyte

:( same here

thienna avatar Jul 27 '22 07:07 thienna

Same here.

Next 12.2.0 React 18.2.0

stanleyume avatar Aug 08 '22 02:08 stanleyume

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 the Component prop in the pages/_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:

  1. Import component dependencies first.
  2. 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.

  1. The Adding a Global Stylesheet docs page should be updated. https://github.com/vercel/next.js/pull/39889
  2. The Error Handling docs page should be updated. https://github.com/vercel/next.js/pull/39890

JohnAlbin avatar Aug 24 '22 06:08 JohnAlbin