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
Scoped styles behave differently in Astro 6 #15907
Astro v6.0.4
Vite v7.3.1
Node v22.22.0
System MacOS (arm64)
Package Manager pnpm
Output static
Adapter none
Integrations none
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
Scoped styles behave differently in Astro 6, which is causing our codebase to break. This seems like a regression, unless it was an intentional breaking change. Seems related to #14032.
When I have an Astro component like this:
<style>
nav {
a {
color: deeppink;
}
}
</style>
<nav>
<Link />
</nav>
I was able to reproduce this issue. The root cause is the @astrojs/compiler upgrade from v2.x to v3.0.0 that ships with Astro 6. In compiler v2.x, CSS nested selectors without & (like nav { a { ... } }) were incorrectly parsed as declarations rather than selector rules, so the inner a was never scoped. Compiler v3.0 correctly parses these as nested selector rules and applies scoping to all selectors, including the inner a, which causes a[data-astro-cid-xxx] to not match <a> elements rendered by child components (since those elements don't carry the parent component's scoping attribute).
I was unable to find a fix for this issue. A fix is already in progress in the compiler repository: withastro/compiler#1153 ("fix: avoid re-scoping nested selectors without &"). In the meantime, a workaround is to use :global() on nested selectors that target child component elements, e.g. nav { :global(a) { color: deeppink; } }.
P4: important. This is a behavioral regression from Astro 5 to Astro 6 that was not documented as a breaking change in the upgrade guide. It affects any codebase using CSS nesting (without &) in scoped styles to target elements rendered by child components — a common pattern. While there is a straightforward workaround (:global()), the change silently breaks existing styles, which violates expected behavior.
The <a> element from the child Link component does NOT have data-astro-cid-j7pv25f6, but the CSS requires it via a[data-astro-cid-j7pv25f6]. The style therefore does not apply.
Root Cause
The behavior change was introduced by the @astrojs/compiler upgrade from v2.x to v3.0.0, which ships with Astro 6.
Specifically, compiler commit 615eb21 (PR withastro/compiler#1144) fixed a bug where CSS nested selectors without & (like nav { a { ... } }) were incorrectly parsed as declarations instead of selector rules. In compiler v2.x, the inner a was never run through the scoping logic, so it remained unscoped. In v3.0, the parser correctly recognizes it as a nested selector rule and applies scoping to it.
This was an intentional bug fix for issue #10721 (:global selector in CSS nesting was broken because nested selectors without & were not parsed at all). However, it has the unintended side effect of breaking styles that target child component elements via CSS nesting.
The scopedStyleStrategy default ('attribute') has NOT changed between Astro 5 and Astro 6.
Key files:
Compiler: lib/esbuild/css_parser/css_parser.go — shouldParseNestedSelector() function (added in v3.0)
Compiler: lib/esbuild/css_printer/astro_features.go — printCompoundSelector() function
Astro: packages/astro/package.json line 120 — @astrojs/compiler: ^3.0.0
Workaround
Using :global() on the nested selector prevents scoping:
nav {
:global(a) {
color: deeppink;
}
}
This produces:
nav[data-astro-cid-xxx]{a{color:#ff1493}}
Which correctly matches the child component's <a> element.
Fix Status
A fix is already in progress: withastro/compiler#1153 ("fix: avoid re-scoping nested selectors without &"). This PR avoids injecting Astro scope for nested selector rules that omit &, which restores the Astro 5 behavior.
Impact
This affects any codebase that uses CSS nesting (without &) in Astro scoped styles to target elements rendered by child components. This is a common pattern and the behavioral change was not documented as a breaking change in the Astro 6 upgrade guide.
This report was made by an LLM. Mistakes happen, check important info.
Activity
[-]Astro v5.10.2 Node v22.14.0 System macOS (arm64) Package Manager pnpm Output static Adapter none Integrations none[/-][+]Scoped styles behave differently in Astro 6[/+]matthewp commentedon Mar 13, 2026
Possibly caused by this, withastro/compiler#1144 i'll take a look
jmbockhorst commentedon Mar 13, 2026
I forgot to mention that I believe this regressed in
v6.0.0-beta.10.astrobot-houston commentedon Mar 13, 2026
I was able to reproduce this issue. The root cause is the
@astrojs/compilerupgrade from v2.x to v3.0.0 that ships with Astro 6. In compiler v2.x, CSS nested selectors without&(likenav { a { ... } }) were incorrectly parsed as declarations rather than selector rules, so the innerawas never scoped. Compiler v3.0 correctly parses these as nested selector rules and applies scoping to all selectors, including the innera, which causesa[data-astro-cid-xxx]to not match<a>elements rendered by child components (since those elements don't carry the parent component's scoping attribute).I was unable to find a fix for this issue. A fix is already in progress in the compiler repository: withastro/compiler#1153 ("fix: avoid re-scoping nested selectors without &"). In the meantime, a workaround is to use
:global()on nested selectors that target child component elements, e.g.nav { :global(a) { color: deeppink; } }.P4: important. This is a behavioral regression from Astro 5 to Astro 6 that was not documented as a breaking change in the upgrade guide. It affects any codebase using CSS nesting (without
&) in scoped styles to target elements rendered by child components — a common pattern. While there is a straightforward workaround (:global()), the change silently breaks existing styles, which violates expected behavior.Full Triage Report
Triage Report: Issue #15907 — Scoped styles behave differently in Astro 6
Reproduction
Status: Reproduced
Created a minimal reproduction with:
index.astro— a page with a<nav>wrapping a<Link />component, with nested CSSnav { a { color: deeppink; } }Link.astro— a simple component rendering<a href="#">test</a>Build output confirmed the issue:
HTML:
CSS:
The
<a>element from the childLinkcomponent does NOT havedata-astro-cid-j7pv25f6, but the CSS requires it viaa[data-astro-cid-j7pv25f6]. The style therefore does not apply.Root Cause
The behavior change was introduced by the
@astrojs/compilerupgrade from v2.x to v3.0.0, which ships with Astro 6.Specifically, compiler commit
615eb21(PR withastro/compiler#1144) fixed a bug where CSS nested selectors without&(likenav { a { ... } }) were incorrectly parsed as declarations instead of selector rules. In compiler v2.x, the innerawas never run through the scoping logic, so it remained unscoped. In v3.0, the parser correctly recognizes it as a nested selector rule and applies scoping to it.This was an intentional bug fix for issue #10721 (
:globalselector in CSS nesting was broken because nested selectors without&were not parsed at all). However, it has the unintended side effect of breaking styles that target child component elements via CSS nesting.The
scopedStyleStrategydefault ('attribute') has NOT changed between Astro 5 and Astro 6.Key files:
lib/esbuild/css_parser/css_parser.go—shouldParseNestedSelector()function (added in v3.0)lib/esbuild/css_printer/astro_features.go—printCompoundSelector()functionpackages/astro/package.jsonline 120 —@astrojs/compiler: ^3.0.0Workaround
Using
:global()on the nested selector prevents scoping:This produces:
Which correctly matches the child component's
<a>element.Fix Status
A fix is already in progress: withastro/compiler#1153 ("fix: avoid re-scoping nested selectors without &"). This PR avoids injecting Astro scope for nested selector rules that omit
&, which restores the Astro 5 behavior.Impact
This affects any codebase that uses CSS nesting (without
&) in Astro scoped styles to target elements rendered by child components. This is a common pattern and the behavioral change was not documented as a breaking change in the Astro 6 upgrade guide.This report was made by an LLM. Mistakes happen, check important info.
buttonelement inLicenseButtonLinkcomponent are not applied correctly in Astro 6 caret-collective/Tally#233