Skip to content

fix: prevent viewtransitions.css from loading with server:defer#15577

Closed
0xRozier wants to merge 3 commits intowithastro:mainfrom
0xRozier:fix/issue-15574-viewtransitions-css-loaded-with-server-defer
Closed

fix: prevent viewtransitions.css from loading with server:defer#15577
0xRozier wants to merge 3 commits intowithastro:mainfrom
0xRozier:fix/issue-15574-viewtransitions-css-loaded-with-server-defer

Conversation

@0xRozier
Copy link
Copy Markdown
Contributor

Summary

Fixes withastro/compiler#1148

  • The @astrojs/compiler incorrectly treats server:defer like a transition:* directive, causing viewtransitions.css to be imported on pages that use server:defer even without any ViewTransitions/ClientRouter usage.
  • After compilation, strip the viewtransitions.css import from compiled output when the source doesn't contain any transition:name, transition:animate, or transition:persist directives.

Root cause

In the compiler's transform.go, server:defer is grouped with transition directives:

if HasAttr(n, TRANSITION_ANIMATE) || HasAttr(n, TRANSITION_NAME) || 
   HasAttr(n, TRANSITION_PERSIST) || HasAttr(n, SERVER_DEFER) {
    doc.Transition = true  // triggers CSS import
    doc.HeadPropagation = true
    getOrCreateTransitionScope(n, &opts, i)
}

This sets doc.Transition = true which makes the compiler emit import "astro/components/viewtransitions.css" even when only server:defer is present.

The long-term fix belongs in @astrojs/compiler, but this provides an Astro-side workaround by stripping the unnecessary CSS import post-compilation.

Test plan

  • Unit tests: 4 tests verifying CSS inclusion/exclusion logic
    • CSS is not included with only server:defer
    • CSS is included with transition:name
    • CSS is included with transition:animate
    • CSS is included with both server:defer and transition:name
  • Integration test: verifies rendered HTML doesn't contain viewtransitions CSS keyframes
  • Build passes

🤖 Generated with Claude Code

The @astrojs/compiler incorrectly treats `server:defer` like a transition
directive, causing viewtransitions.css to be imported on pages that use
server:defer even without any ViewTransitions/ClientRouter usage.

Strip the viewtransitions.css import from compiled output when the source
doesn't contain any transition:name, transition:animate, or
transition:persist directives.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Feb 19, 2026

🦋 Changeset detected

Latest commit: 860bfeb

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the pkg: astro Related to the core `astro` package (scope) label Feb 19, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Feb 19, 2026

Merging this PR will not alter performance

✅ 9 untouched benchmarks


Comparing 0xRozier:fix/issue-15574-viewtransitions-css-loaded-with-server-defer (860bfeb) with main (d789452)

Open in CodSpeed

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes issue #15574 where viewtransitions.css is incorrectly loaded on pages using server:defer without any View Transition directives. The root cause lies in @astrojs/compiler, which incorrectly groups server:defer with transition directives when determining whether to import the ViewTransitions CSS. This PR implements a post-compilation workaround in Astro's compile step to strip the unnecessary CSS import.

Changes:

  • Added post-compilation logic to strip viewtransitions.css import when no transition directives are present in source
  • Added unit tests verifying CSS inclusion/exclusion logic for various directive combinations
  • Added integration test to verify CSS is not included in rendered HTML for server:defer-only pages

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
packages/astro/src/core/compile/compile.ts Adds post-compilation check to strip viewtransitions.css import when only server:defer is used without transition directives
packages/astro/test/units/compile/viewtransitions-css.test.js New unit test file with 4 tests covering CSS import behavior across different directive combinations
packages/astro/test/server-islands.test.js Adds integration test verifying viewtransitions CSS is not included in rendered HTML
.changeset/fix-viewtransitions-css-server-defer.md Changeset documenting the patch fix

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@martrapp
Copy link
Copy Markdown
Member

martrapp commented Feb 19, 2026

Hi @0xRozier 👋🏼 thank you for addressing the issue so fast!

I saw that you repair the unnecessary input inside the astro package after the fact.
I think it would be a more maintainable solution to address the root cause instead.

Did you have a chance take a look at the compiler repository?

…lint error

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@0xRozier
Copy link
Copy Markdown
Contributor Author

Hi @martrapp, thanks for the feedback!

I agree that the compiler would be the ideal place for this fix. Unfortunately, I'm not familiar with Go and the compiler internals, so contributing a fix there isn't really something I can take on.

This workaround is intentionally scoped and defensive — it only strips the import when the source genuinely has no transition:* directives, so it should be safe as a stopgap. If someone with compiler expertise wants to address the root cause in withastro/compiler, this patch could then be removed.

Let me know if this approach works for you, or if you'd prefer to wait for a compiler-side fix instead!

@martrapp
Copy link
Copy Markdown
Member

Hi @0xRozier, thanks for the honest reply — I really appreciate the transparency.

That makes sense, and your workaround sounds sensible as a stopgap. I will take a look at the compiler and see if I can make any progress there.

@martrapp
Copy link
Copy Markdown
Member

Opened withastro/compiler#1149

@martrapp
Copy link
Copy Markdown
Member

Closing this PR in favour of #1149

@martrapp martrapp closed this Feb 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: astro Related to the core `astro` package (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ViewTransitions.css loaded when a server:defer component is present on a page

3 participants