Skip to content
This repository was archived by the owner on Jul 11, 2026. It is now read-only.

About

Reproducer for SvelteKit inlined CSS bug

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

Repository files navigation

SvelteKit: relative url()s in inlined CSS 404 with paths.relative: false (regression in 2.65.0)

With inlineStyleThreshold set and paths.relative: false, CSS inlined into <style> tags keeps its relative url() references (e.g. url(./red-hat-mono-*.woff2)). The browser resolves those against the page URL instead of the original stylesheet location, so fonts and other CSS assets 404.

Reproduce

pnpm install
pnpm verify   # builds, then greps build/index.html for relative url()s

Expected: url(/_app/immutable/assets/red-hat-mono-*.woff2) Actual: url(./red-hat-mono-*.woff2) → resolves to /red-hat-mono-*.woff2 → 404

Minimal config (svelte.config.js):

kit: {
  adapter: adapter(),            // not adapter-specific; static just makes it easy to inspect
  paths: { relative: false },
  inlineStyleThreshold: 16384,
}

Both options are required: with the default paths.relative: true, the inlined URLs are rewritten correctly.

Affected versions

Tested by building this repro against each version:

@sveltejs/kit inlined url()
2.50.1 – 2.64.0 url(/_app/immutable/assets/…) works
2.65.0 – 2.69.2 (latest) url(./…) broken

Root cause

Two changes interact:

  1. Since #15153 (kit 2.50.2), inlined client CSS is passed through fix_css_urls(), but only behind this gate in src/exports/vite/build/build_server.js (line 69 in 2.69.2):

    if (kit.paths.assets || kit.paths.relative) {
      prepare_css_for_inlining = (css, eager_assets) => { /* fix_css_urls(...) */ };
    }

    With paths.relative: false and paths.assets unset, the gate is false and prepare_css_for_inlining stays the identity function — relative url()s are inlined verbatim.

  2. That gate was harmless until #15936 (kit 2.65.0) switched the client build to Vite base: './' plus a renderBuiltUrl hook. Before, a build with relative: false used an absolute base, so CSS assets already contained absolute url(/_app/…) and needed no fixing. Since 2.65.0, emitted CSS always contains relative url()s — fine for external stylesheets (they resolve against the CSS file), wrong for inlined ones. The gate now skips exactly the rewrite that is always needed.

    #16026 fixed another fallout of #15936 for relative: false apps (JS chunk paths, #16013) but did not touch the CSS-inlining path.

Verified fix

Making the rewrite unconditional (dropping the gate) fixes it: patching node_modules/@sveltejs/kit/src/exports/vite/build/build_server.js to if (true) and rebuilding produces url(/_app/immutable/assets/…). The runtime ${assets}/${base} interpolation inside fix_css_urls already handles the default empty values correctly.

Workarounds

  • Keep the default paths.relative: true, if the deployment allows it (not always possible, e.g. when a prerendered 404 page is served at any unknown path — GitHub Pages-style 404.html, SPA fallbacks — where relative asset paths would resolve against the browser URL and break).
  • Remove inlineStyleThreshold — external stylesheets resolve relative url()s correctly.
  • paths.assets cannot help: kit's config validation only accepts '' or a fully-qualified scheme:// URL, i.e. an actual separate asset host.

References

  • #15936 — introduced the regression in 2.65.0 (client build switched to relative base + renderBuiltUrl)
  • #15153 — added the kit.paths.assets || kit.paths.relative gate (2.50.2)
  • #16013 / #16026 — sibling regression of #15936, fixed for JS chunk paths only
  • #6720 — 2022 issue with the same symptom, fixed back then by #13068 (an inlining approach later replaced)

About

Reproducer for SvelteKit inlined CSS bug

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages