My HTML report lost its CSS

Unstyled text, a blank page, or a chart-shaped hole. Five causes, in roughly the order they occur. The browser console names the one you have — open it first.

1. Only the entry file travelled

Most tools that emit "an HTML report" emit a directory: index.html plus report_files/, assets/, jacoco-resources/, _static/ — the naming varies, the shape doesn't. Copy the .html out of it and every stylesheet and script reference points at nothing.

Console says: 404s on .css and .js.

Fix: move the whole directory, or publish the whole directory. If the tool has a self-contained mode, use it — nbconvert --embed-images, Altair's inline=True, Extent's offline mode, Plotly's include_plotlyjs=True.

2. It's being opened from file://

A local page has an opaque origin. Module scripts (<script type="module">) and fetch/XMLHttpRequest to sibling files are blocked by the same-origin rules — deliberately, and with no flag worth setting. Reports that load results as JSON (Vitest, several coverage UIs) can't work this way at all; their own docs tell you to run a local server first.

Console says: a CORS error on a module, or Cross origin requests are only supported for protocol schemes: http, https…

Fix: serve it over HTTP. python -m http.server proves the diagnosis; a published URL fixes it for everyone rather than for you.

3. A Content-Security-Policy is refusing the subresources

CI artifact viewers commonly serve artifacts under a strict CSP, which is why the same file looks perfect locally and naked in the browser. Jenkins is the best-known example — see the Jenkins CSP fix — and GitLab's and Azure's artifact viewers have their own constraints.

Console says: Refused to load the stylesheet… or Refused to execute inline script… because it violates the CSP.

Fix: stop relying on the artifact viewer as a rendering surface. It is a file store that happens to return text/html.

4. The report was pasted somewhere that isn't a browser

Email clients strip <script> and external stylesheets, and Outlook on Windows renders with the Word engine — no flexbox, no grid. Chat clients preview markup as text. See emailing an HTML report.

Fix: send a link, not markup.

5. It needs the network, and the network isn't there

A report that loads its libraries from a CDN renders as a skeleton on a locked-down laptop, on a plane, or inside an air-gapped environment.

Fix: generate the self-contained variant when the audience might be offline. When they're online, CDN-loaded reports are fine — subresources fetched inside Comma's sandboxed frame aren't governed by the app's CSP, and the common visualization CDNs (jsDelivr, unpkg, cdnjs, esm.sh) are allow-listed anyway.

Making it not happen again

Publish the output directory once and share the URL:

  • index.html becomes the report body.
  • The CSS, JS, JSON and images upload alongside it, and their relative references are rewritten to the uploaded copies. That single step removes causes 1, 2 and 3.
  • Scripts run inside a sandboxed iframe (allow-scripts, no allow-same-origin), so interactivity survives — interactive HTML reports.

Drag the folder (or a zip of it) into the app, or publish it from CI so the fixed version is the one everyone gets.

Limits: entry HTML 5 MB; assets 25 MB per file, 250 MB and 500 files per report.

Try it

Comma is free — unlimited reports, unlimited commenters, unlimited revision history.

Publish the whole report folder →

Related