You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Inlined styles: SSR and client end up with a different CSS cascade, so computed styles change on hydration #36620
Run npm run build && npm run preview (dev mode doesn't inline styles).
Open the preview with JS disabled or with CPU throttling, then let it hydrate.
#case-a (component rule vs global CSS) and #case-b (parent vs child root) start at 88px / red and switch to 120px / green on hydration. On 4.5.2 they stay at 120px / green.
The page must be opened without using the browser cache.
Describe the bug
The order of equal-specificity rules coming from different files isn't guaranteed, and this issue doesn't ask for a particular order. It's about consistency: the server-rendered <head> and the <head> after hydration contain the same rules in a different order, so the same page renders differently before and after hydration.
Expected: computed styles are the same before hydration, after hydration and after client-side navigation, whatever order Nuxt picks.
Actual (4.6.2): both elements render at 88px / red from the SSR HTML and switch to 120px / green during hydration, which is a layout shift on every hard load. Client-side navigation renders 120px right away.
Computed height of #case-a / #case-b. "Before hydration" is measured at readyState === 'interactive', before any module script runs, with all stylesheets loaded:
version
before hydration
after hydration
4.5.2
120px / 120px
120px / 120px
4.6.2
88px / 88px
120px / 120px
<head> (stylesheets only):
<!-- 4.6.2 SSR: the shared chunk's <link> is dropped because its CSS is inlined --><style>.banner{background:#2e8b57;height:120px}</style><style>.product-card[data-v-84345cbb]{background:#2e8b57;height:120px}</style><style>.base-card[data-v-92b00755]{background:tomato;height:88px}</style><linkrel="stylesheet" href="/_nuxt/entry.CL7L9PkT.css"><!-- 4.6.2 after hydration: Vite's preload helper appends the chunk CSS to the end of <head> -->
...
<linkrel="stylesheet" href="/_nuxt/entry.CL7L9PkT.css"><linkrel="stylesheet" href="/_nuxt/ProductCard.CoJAPe-B.css"><!-- 4.5.2 SSR: the duplicate <link> was still rendered, so SSR matched the client -->
...
<linkrel="stylesheet" href="/_nuxt/entry.CL7L9PkT.css"><linkrel="stylesheet" href="/_nuxt/ProductCard.CoJAPe-B.css">
Every equal-specificity conflict between an inlined rule and a linked rule, or between two inlined rules, can resolve one way in SSR and the other way once the client appends the stylesheet.
History. This isn't new in 4.6, but 4.6 widened it:
In 4.5.2 the same mismatch already exists for page components: their CSS is inlined and never linked, so entry.css comes after the page's <style> in SSR and before the page CSS after hydration.
Check the box below or use the @coderabbitai plan command to generate an implementation plan and prompts that you can use with your favorite coding assistant.
Create Plan
🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your .coderabbit.yaml:
issue_enrichment:
auto_enrich:
enabled: false
💬 Have feedback or questions? Drop into our discord!
Not a duplicate of #33041. That issue covers parent vs child order of inlined <style> tags, which is case B here (still open for children in shared chunks).
The main part here is case A: in 4.6, inlined component styles render before <link rel="stylesheet"> (global CSS), and #36056 / #36060 drop the duplicate chunk link that kept SSR and client in sync. Vite appends it on hydration, so any equal-specificity override of global CSS flips. Stable on 4.5.2, flips on 4.6.2.
This isn't a request for a specific order, only for SSR and the hydrated client to resolve the same cascade.
Activity
coderabbitai commentedon Oct 16, 2026
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
pont1s commentedon Oct 16, 2026
Not a duplicate of #33041. That issue covers parent vs child order of inlined
<style>tags, which is case B here (still open for children in shared chunks).The main part here is case A: in 4.6, inlined component styles render before
<link rel="stylesheet">(global CSS), and #36056 / #36060 drop the duplicate chunk link that kept SSR and client in sync. Vite appends it on hydration, so any equal-specificity override of global CSS flips. Stable on 4.5.2, flips on 4.6.2.This isn't a request for a specific order, only for SSR and the hydrated client to resolve the same cascade.