Repository navigation
Bundling repeated CSS imports drops later media conditions #6249
Description
Describe the bug
Bundling a composition can drop its screen styles when a linked stylesheet imports the same local file first for print and then for screen. The authored page has a green background; the bundled page has a transparent background and appears white.
This reproduces with the published @hyperframes/core@0.8.193 package and baseline main ab57d0ee1446846d81d25d7d2411ec03e9927005. The compiler is unchanged on current main 9aadc0b9b99d92afd25215228878cee23ea47a0f.
Minimal reproduction
Create these three files under repro/:
index.html:
<!doctype html>
<html><head>
<link rel="stylesheet" href="main.css">
<style>html,body{margin:0}#box{width:320px;height:180px}</style>
</head><body>
<div id="box" data-composition-id="root" data-width="320"
data-height="180" data-duration="1"></div>
</body></html>main.css:
@import "shared.css" print;
@import "shared.css" screen;shared.css:
#box { background-color: rgb(0, 128, 0); }Steps to reproduce
With @hyperframes/core@0.8.193 available, run:
import { writeFile } from "node:fs/promises";
import { bundleToSingleHtml } from "@hyperframes/core/compiler";
await writeFile("repro/bundled.html", await bundleToSingleHtml("./repro", {
runtime: "placeholder",
staticGuard: false,
}));Serve repro/ over HTTP and open index.html and bundled.html in a browser using screen media. Inspect the computed backgroundColor of #box.
Expected behavior
Both imports retain their conditions. The authored page and bundle both show rgb(0, 128, 0).
Actual behavior
Only the print import survives. On screen, the bundle reports rgba(0, 0, 0, 0) and appears white. The same loss happens when two parent stylesheets import a common dependency under different inherited media conditions. Repeating an unconditional dependency through two parents can also change cascade order.
Environment
- Latest published core: 0.8.193, downloaded from npm and integrity checked; its built public compiler was executed.
- Baseline main:
ab57d0ee1446846d81d25d7d2411ec03e9927005; compiler and parsers unchanged on current main9aadc0b9b99d92afd25215228878cee23ea47a0f. - Linux x64, Node 26.11.1, Bun 1.4.1, Chrome 152.0.7977.42.
- A static CSS/bundling reproduction. No MP4 render is claimed.
Additional context
inlineCssFile shares a global visited-file set across sibling imports and drops every later occurrence. Cycle detection needs the active ancestor chain instead. CSS requires separate processing of each occurrence: https://www.w3.org/TR/css-cascade-5/#import-processing.
Related #922 and #923 introduced import expansion and diamond deduplication. #4664 handles conditional stylesheet links. This report concerns repeated recursive local CSS imports, including the conditions inherited from their parents. Public issue, PR, review, comment and discussion searches found no matching report or active implementation in the checked sources.
Activity
miguel-heygen commentedon Oct 24, 2026
Thanks for the clear report. Confirmed on 0.8.193 and current main: when the bundler inlines a linked stylesheet's
@importrules, it remembers every file it has already inlined anywhere in that sheet's import tree and drops any later import of the same file. The second import disappears along with its media condition, so with your files the bundle keeps only the@media printcopy, and Chrome shows the authored page green and the bundled page transparent.Reproduced with the published
@hyperframes/core@0.8.193and your exact files and script: the bundled<style>contains only the print block, and#boxcomputesrgb(0, 128, 0)inindex.htmlandrgba(0, 0, 0, 0)inbundled.html.#6250 is the fix to follow for this.