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

CSS Modules styles defined in wrong order in development mode #13092

Closed
jensmeindertsma opened this issue May 19, 2020 · 31 comments · May be fixed by #16129
Closed

CSS Modules styles defined in wrong order in development mode #13092

jensmeindertsma opened this issue May 19, 2020 · 31 comments · May be fixed by #16129
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.). Webpack Related to Webpack with Next.js.

Comments

@jensmeindertsma
Copy link

jensmeindertsma commented May 19, 2020

Bug report

Describe the bug

In development mode, when a page imports styles from a .module.css file ( import styles from "./home.module.css" ) and then imports another component after that ( import { Container } from "../components/Container" ), and passes the imported styles to the component like <Container className={styles.blue}>, these styles get overriden by the imported component. This component has it's own styles and passes the className prop to a DOM element:

import styles from "./Container.module.css";

function classes(...classNames) {
  const joined = classNames.join(' ');
  return joined;
}

export const Container = ({
  children,
  className= "",
}) => {
  return (
    <div className={classes(styles.container, className)}>
	 {children}
    </div>
  );
};

The Container has the following style:

.container {
	background-color: yellow;
}

But the page provides the following style:

.blue {
	background-color: blue;
}

In development, the styles are injected into the head as follows:

<style>
.index_blue__3Iu-s {
	background-color: blue;
}
</style>
<style>
.Container_container__1UmhU {
	background-color: yellow;
}
</style>

In production, these styles are combined into one stylesheet:

.Container_container__1UmhU {
    background-color: #ff0
}

.index_blue__3Iu-s {
    background-color: #00f
}

As you can see, there is a difference in order. This causes the inconsistency across environments with CSS ( yellow in development, blue in production ).

I believe that the production result is the correct one, as you should be able to override the component styles.

I'd be happy to try to contribute to a fix. However, I am a beginner developer so I might need some guidance.

To Reproduce

Clone my reproduction repository and run npm run dev to see the styles applied incorrectly, and run npm run build; npm run start to see that the styles work as intended.

Expected behavior

I would expect that in both development and production mode the classes get defined in the same order so that the styles are applied correctly.

System information

  • OS: Windows 10
  • Browser: Chrome 81.0.4044.138
  • Version of Next.js: 9.4.1
  • Version of Node.js: 12.16.1

More information

The style tags are injected by the code in this file. It uses style-loader in development and the MiniCssExtractPlugin in production. What is the reason as to why it isn't used in development mode?

NEXT-1386

@Timer Timer modified the milestones: 9.4.2, 9.4.3 May 19, 2020
@jensmeindertsma jensmeindertsma changed the title CSS Modules styles applied in wrong order in development mode CSS Modules styles defined in wrong order in development mode May 23, 2020
@jensmeindertsma
Copy link
Author

@Timer I rewrote the issue as it wasn't that clear previously.

@jensmeindertsma
Copy link
Author

Even moving the import to the bottom of the file doesn't work perfectly, because changing the component className still moves that class below the page styles.

I'd be happy to work on this, but I need some direction. I tried using MiniCssExtractPlugin that's already used in production also for development mode but that causes some errors too. Could someone explain why there is a different approach to styles across development and production mode? @Timer

@petewarman
Copy link

I think the order of the imports matters - in the example page you have

import styles from "./index.module.css";
import { Container } from "../components/Container";

So I would expect the source order of the compiled css to be

  1. page styles
  2. component styles

Therefore in your example the component style should override the page styles and the background should be yellow. ie. the dev mode is correct. Worryingly it's the production mode that gets it wrong.

@jensmeindertsma
Copy link
Author

@petewarman Moving the styles import to after the component import works, until I modify the component too much (changing the name of the class it applies to the div). Then the styles of the component are re-inserted after the page styles despite the page styles import being the last import in the file

@Timer Timer modified the milestones: 9.4.3, 9.4.4 May 28, 2020
@giuseppeg
Copy link
Contributor

giuseppeg commented Jun 2, 2020

This is likely a generic issue with CSS Modules and not Next.js specific https://twitter.com/giuseppegurgone/status/1084921816030896135
https://twitter.com/giuseppegurgone/status/1166043099900076033

@jensmeindertsma
Copy link
Author

You might be right. Although I do still think the loading order should be consistent across environments

@giuseppeg
Copy link
Contributor

fair point

@jensmeindertsma
Copy link
Author

Going to keep this open because this is something that Next.js could improve. I'm willing to help work on it.

@Timer Timer modified the milestones: 9.4.5, 9.x.x Jun 29, 2020
@kylemh
Copy link
Contributor

kylemh commented Jul 12, 2020

I'm not even sure what to do as a workaround for this.

I think an easy solution would be to automatically apply page-specific identifiers as part of the css modules hash generation, but the ability to configure that isn't exposed.

In my app today, I guess I could pass the style attribute and inline my styles, but I have a heavy reliance on PostCSS stuff that can't be leveraged in my JS.

I tried using classNames with dynamic values and .bind() to no avail... Even !important wont work because if more pages are passing one-offs to the same components, those will be fighting eachother.

@kylemh
Copy link
Contributor

kylemh commented Jul 17, 2020

For this deployment you can hover on one of these three image buttons, and see the whole page's content shift:

Each of those images is a next/link, so a route is pre-fetched... including it's stylesheet. The styles on that page end up overriding conditional styles or styles passed in via a className prop, for a component used on both pages (namely, the "HeroBanner").

Basically, prefetched stylesheets have the potential to obliterate rules on the current page.

The only idea I've had to solve this inside Next.js would be to make a route-named CSS class, wrapping each pages styles in that class ruleset, and then add class="route-named-class" to the __next element, but that's just off the top of my head and I'm sure it's whack compared to what y'all could come up with. A temporary fix would be to not prefetch the page's stylesheet maybe, but that might make transitions look janky. Another idea could be to ensure the current page's stylesheet is resolved last and popped off the top when route changes actually begin?

@kylemh
Copy link
Contributor

kylemh commented Jul 17, 2020

Ah shit, @Timer I think my issue and @jensmeindertsma are actually different errors. My problem is happening in production and it's not about improper ordering... lemme make a repro repo and a new issue

@kylemh
Copy link
Contributor

kylemh commented Jul 18, 2020

@Timer #15284

@Timer Timer modified the milestones: 9.x.x, iteration 6 Jul 25, 2020
@timneutkens timneutkens added the linear: next Confirmed issue that is tracked by the Next.js team. label Jul 4, 2023
@timneutkens timneutkens added linear: next Confirmed issue that is tracked by the Next.js team. and removed linear: next Confirmed issue that is tracked by the Next.js team. labels Jul 4, 2023
@Enkratia
Copy link

Enkratia commented Nov 13, 2023

When i use use client in one component => order of CSS modules stop to work in entire project.
When i delete use client in this component => order of CSS modules works again in entire project.

I resolved the problem by adding additional intermediate server component which now contains my client component. Looks like the reason of this is circular reference.

edit: i got this problem again.
I resolved the problem by adding intermediate client component instead of additional intermediate server component this time.

edit: for the first time the reason is nested layout, not "use client".
Unresolvable

@waldell
Copy link

waldell commented Dec 5, 2023

Would love to hear if this is gonna be fixed? I spent hours on debug and researching until I found the issue, googled it and found this issue.
I mean, you really should expect this kind of basic thing to work in such a large library as Next

@jackvividseats

This comment was marked as spam.

@yunsii
Copy link
Contributor

yunsii commented Dec 20, 2023

#10148
#16630

And this issue all are css order related bugs, but it still not work as expected fot now 😦

@kotAPI
Copy link

kotAPI commented Dec 21, 2023

This is most definitely a bug in Nextjs, a pretty evasive one. I've followed thread after thread and it led me to here. It seems that vercel team is having a tough time trying to figure out how to fix this- this has been re-surfacing since 2019 and multiple times this issue has been closed in favor of new threads.

This behaviour is erratic and unpredictable.
I have a relatively simple project with 3 css files

// layout.js
import './globals.css' // This is tailwind css file
import "./base.tokens.css"; // my css 1
import "@radui/ui/themes/default.css"; // other external css library file

This works perfectly fine on local, but once it's built in production, it behaves unexpectedly. I tried reordering it in all possible permutation, but the styles in first files always overrides the other 2 files

@harryfinn
Copy link

Have been encountering the same issue outline both here and previously in #16630.

Using app router on Next.js v14.0.4 I am unable to override css vars from an imported external package, even when ordering my overrides below the imported package.

The only work around I've found to work both in local dev and generated prod build is the one outline here #16630 (comment)

Very keen to know if there are any alternatives at this stage, or whether it's a waiting game for Turbopack at this point?

@landsman

This comment was marked as spam.

@eqbit
Copy link

eqbit commented Mar 29, 2024

For everyone looking for a solution - looks like it is fixed in v14.2.0-canary.28

@thexpand
Copy link

Happens again in v14.2.2

@r1tsuu

This comment has been minimized.

@samcx samcx added bug Issue was opened via the bug report template. and removed kind: bug labels Apr 30, 2024
@samcx
Copy link
Member

samcx commented Apr 30, 2024

Closing this since this fix was landed → #51030 (comment).

@samcx samcx closed this as completed Apr 30, 2024
@thexpand
Copy link

@samcx I don't understand why you're closing this when it hasn't been fixed. Literally, the issue you shared has comments of people who tried the latest version and it still breaks.

@samcx
Copy link
Member

samcx commented Apr 30, 2024

@thexpand There are different CSS-related issues shared in that thread, so I haven't closed that one. The PR in that comment specifically describes a fix for CSS Modules ordering.

The version you shared I believe does not have that PR fix, but it will be in the latest canary.

CleanShot 2024-04-30 at 12 33 25@2x

@thexpand
Copy link

Oh, okay, but the comment you shared is misleading - it says the fix landed on v14.2.0-canary.28, which I thought was released with 14.2.0, but maybe it wasn't.

Copy link
Contributor

This closed issue has been automatically locked because it had no new activity for 2 weeks. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Issue was opened via the bug report template. linear: next Confirmed issue that is tracked by the Next.js team. locked Upstream Related to using Next.js with a third-party dependency. (e.g., React, UI/icon libraries, etc.). Webpack Related to Webpack with Next.js.
Projects
None yet
Development

Successfully merging a pull request may close this issue.