next.js: CSS Modules styles defined in wrong order in development mode

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

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 45
  • Comments: 26 (9 by maintainers)

Most upvoted comments

Have been encountering the same issue outline both here and previously in https://github.com/vercel/next.js/issues/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 https://github.com/vercel/next.js/issues/16630#issuecomment-1762463616

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

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

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

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

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.

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

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

@timneutkens / @Timer im guessing this is a “won’t fix” until Turbopack?