[NEXT-1308] Css is imported multiple times and out of order in /app dir #68684
Replies: 124 comments 1 reply
-
This PR #50406 seems like it should have fixed this issue, but I see the problem in my repro repositories |
Beta Was this translation helpful? Give feedback.
-
CSS modules seem to be working ok. Removed vanilla-extract from this repro, and imported the same CSS from CSS module in the page and layout, and set it on the Edit: it works like that if both the page and layout are RSC. When I use |
Beta Was this translation helpful? Give feedback.
-
This issue is still present in the latest canary (13.4.7-canary.1)
Here is a minimal repro with easy-to-reproduce test cases. https://codesandbox.io/p/sandbox/next-51030-hlj722?file=%2Fapp%2Fpage.tsx%3A1%2C1 |
Beta Was this translation helpful? Give feedback.
-
The current order of imports wreaks havoc when CSS Cascade Layers are being used. The defined layer precedence that belongs in the root layout file gets read after the application of layers in child components. This causes the defined layer precedence to be ignored in favor of something random (https://css-tricks.com/css-cascade-layers/#aa-establishing-a-layer-order), and can make routes unusable. This issue surfaced for me when updating up from 13.4.4 to 13.4.5 or 13.4.6. |
Beta Was this translation helpful? Give feedback.
-
One workaround I'm currently using is to make the children CSS more specific: |
Beta Was this translation helpful? Give feedback.
-
For https://codesandbox.io/p/sandbox/next-51030-hlj722?file=%2Fapp%2Fpage.tsx%3A1%2C1, it becomes very tricky if your CSS code itself has conflicts and some behaviors are undefined. For example when a dynamic component has loaded, its CSS might cause side effects to other parts of the page, which is expected. For example, if you have a layout like this: import style1 from 'a.module.css'
import style2 from 'b.module.css'
<button className={style1.btn + ' ' + style2.btn}> The styles that imports later will override previous ones, so In general, we recommend you to use CSS |
Beta Was this translation helpful? Give feedback.
-
@shuding, I appreciate you taking the time to look into this example.
I wouldn't call styles override a conflict. Overriding base component styles in a descendant component is a pretty common technique. Isn't that what "C" in CSS stands for?
The above example is a module-scoped CSS that doesn't have any global side-effects.
Yes, you are absolutely correct, and that's the desired behavior that we are unfortunately not able to achieve under the app router.
In theory, yes. But it's not the case in the above example, isn't it? |
Beta Was this translation helpful? Give feedback.
-
@shuding if you'll please read my comment below,
|
Beta Was this translation helpful? Give feedback.
-
Thanks! I'll go through all the reproductions and think about an improvement in the next couple of days! I understand that the confusion caused by the new architecture. In general scoped CSS itself doesn't have conflicts, but the order and duplication might cause the styles to conflict (override each other). I'll give you an example: layout: → layout.css If the module that contains the However when page is rendered, Previously in the pages directory, all styles will be packed into one CSS file. But here we need to generate one CSS per layout and page because they can be loaded separately. That said, we still have some ideas to improve it. Like changing the CSS modules hashing algorithm to make it base on the layer, or deduplicate styles that are already in its parent layer. Will keep you updated in this issue. |
Beta Was this translation helpful? Give feedback.
-
If I understand the latter suggestion correctly, this seems to me like the right approach. If a build system produces hashed rule/class names based on the rule contents (e.g., To your point, if there's perfect purity, this won't be a problem, but it's also reasonably unrealistic that there wouldn't be things like rules applied to descendent selectors (and probably some non-negigible number of other scenarios) on class names that have a high likelihood of their precedence being trumped by the same properties in a rule duplicated in |
Beta Was this translation helpful? Give feedback.
-
I'm also encountering the same behaviour. For my use case, I'm creating standard UI/layout components that I want to use across multiple pages and components – these components have The problem is, as mentioned above, changing between routes/different app runs can result in different CSS load orders in addition to a huge amount of duplicate CSS. For example: // components/layout/Section.tsx
import styles from '../../styles/layout/Section.module.css';
interface Props extends React.ComponentProps<'section'> {
fullWidth?: boolean;
}
export default function Section(props: Props) {
const { fullWidth, ...remainingProps } = props;
return (
<section
{...remainingProps}
className={[styles['section'], props.className].join(' ')}
data-fullwidth={fullWidth}
>
{props.children}
</section>
);
} Navigating from For now, as a partial fix, I have managed to use css Would be interested to know if there is a better way to go about this. I can provide more detailed examples/reproductions if necessary. |
Beta Was this translation helpful? Give feedback.
-
Have a quick hack fix for the css layer order here #16630 (comment) |
Beta Was this translation helpful? Give feedback.
-
Is there already a solution for css that is loaded multiple times if you use the "use client" mode? |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
I just ended up writing a simple Webpack plugin that removes duplicate rules by their class names (which isn't a good idea in pratice, but has worked well enough for my needs). I've only tested this with CSS generated with Vanilla Extract, and it doesn't support route groups, but someone may find it useful. |
Beta Was this translation helpful? Give feedback.
-
Yes! That's the example used :) |
Beta Was this translation helpful? Give feedback.
-
@samcx I'm still having the problem, even with the v14.2.5 release. Additionally tested this in 15.0.0-canary.63 with no luck. Here's my repro: https://github.com/kutsan/nextjs-css-duplicates-issue When I inspect the title styles, I'm seeing duplicates. So far, I've found two possible solutions:
I'm not sure why these work, but I hope this helps. |
Beta Was this translation helpful? Give feedback.
-
Might be the same issue I am facing. Also related to the "use client" directive |
Beta Was this translation helpful? Give feedback.
-
Here is a minimized RE-PRO |
Beta Was this translation helpful? Give feedback.
-
Turbopack is only ready for development, production still has 537 test remaining to be fixed (https://areweturboyet.com/build). Most of the remaining tests are related to CSS |
Beta Was this translation helpful? Give feedback.
-
It is happening in turbo development though, I've opened a new issue #68412 since it might not be entirely related with this one and has a minimal repo to showcase the issue. |
Beta Was this translation helpful? Give feedback.
-
Following. I believe I am also running into this. Even with the merge of #67373, when using Further, with
|
Beta Was this translation helpful? Give feedback.
-
@pixelchutes Is it possible to create a minimal |
Beta Was this translation helpful? Give feedback.
-
@samcx Let me see if I can put something together! Creating a reminder to revisit early next week 👍🏼 |
Beta Was this translation helpful? Give feedback.
-
@samcx I think Paco made a perfect repro of this issue before, it was ignored for some reason. Here's is it, did you saw it? https://github.com/pacocoursey/next-cascade-layers |
Beta Was this translation helpful? Give feedback.
-
This is a great example! |
Beta Was this translation helpful? Give feedback.
-
Are there any internally discussed updates we should know of? CSS is a pretty crucial part 😥 |
Beta Was this translation helpful? Give feedback.
-
@subproject22 Paco's example wasn't ignored. There was actually no broken behavior here, we just had to update the import order, which matters. I shared this here (earlier comment) → #51030 (comment). @Netail Nothing to share yet. Will be considering moving this to discussions soon, as this thread is becoming too broad (everyone is just piling their CSS issue here)—we need to actually isolate an issue to the actual specifics at play, such as your Client ↔ Server CSS issue that you reported. We are also tackling this old CSS issue as well → #33286. |
Beta Was this translation helpful? Give feedback.
-
@samcx i created default next.js app with 1 server component, 1 LIink, 1 Image, 1 css module. Can you explain why HMR doesn't work? This problem persists more than 1 year. If repro is needed: https://github.com/Enkratia/css-reload-show |
Beta Was this translation helpful? Give feedback.
-
@Enkratia Please open a separate bug report detailing your HMR issue with CSS. |
Beta Was this translation helpful? Give feedback.
-
Verify canary release
Provide environment information
Which area(s) of Next.js are affected? (leave empty if unsure)
App directory (appDir: true)
Link to the code that reproduces this issue or a replay of the bug
https://github.com/ssijak/next-css-issue-not-working-simple
To Reproduce
Just start the app and check the styling on the buttons. Styles are imported multiple times wherever
Button
was used (page and layout) and order is also not deterministic, so it can be imported in different order on different app runs.This is another/same simple repro difference is just that it uses turbo and transpiles the UI lib, I started with that but figured that the issue is happening without it too https://github.com/ssijak/next-css-issue-not-working
Describe the Bug
-Same styles are imported multiple times
-Order of imports is not deterministic
Screenshot: https://share.cleanshot.com/nq35j7vh
Expected Behavior
Same styles should be imported once. Starting the app multiple times should not produce different results (ordering of CSS, impacting specificity)
Which browser are you using? (if relevant)
No response
How are you deploying your application? (if relevant)
No response
From SyncLinear.com | NEXT-1308
Beta Was this translation helpful? Give feedback.
All reactions