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?
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 45
- Comments: 26 (9 by maintainers)
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
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
So I would expect the source order of the compiled css to be
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?