Skip to content

fix(canvas): PDF export comes out blank in Safari - #9790

Open
dfliess wants to merge 3 commits into
rilldata:mainfrom
dfliess:dfliess/canvas-pdf-safari-blank
Open

fix(canvas): PDF export comes out blank in Safari#9790
dfliess wants to merge 3 commits into
rilldata:mainfrom
dfliess:dfliess/canvas-pdf-safari-blank

Conversation

@dfliess

@dfliess dfliess commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

In Safari every chart in a canvas PDF export comes out blank, headers only. Export twice without reloading and the second one is correct. Chrome and Firefox are unaffected.

html-to-image clones a <canvas> into an <img> nested in the <foreignObject> it serializes, and WebKit paints that SVG before the nested image has decoded. captureCanvasBlocks rasterizes each block once, so every chart is always a first capture.

Known upstream and unfixed. bubkoo/html-to-image#569 reports canvases blank on Safari across macOS, iOS and iPadOS; capturing twice is the standing workaround there (bubkoo/html-to-image#292), and the open fix (bubkoo/html-to-image#498) keys off a user agent regex. So it lives here for now, behind a probe instead.

Commits: probe for the affected browser and capture those blocks twice; stop paginate magnifying captures narrower than the page; render the export view at the canvas's max_width so the document does not depend on the exporter's window.

Same capture path as #9770.

Checklist:

  • Covered by tests
  • Ran it and it works as intended
  • Reviewed the diff before requesting a review
  • Checked for unhandled edge cases
  • Linked the issues it closes
  • Checked if the docs need to be updated. If so, create a separate Linear DOCS issue
  • Intend to cherry-pick into the release branch
  • I'm proud of this work!

dfliess added 3 commits August 5, 2026 13:37
html-to-image clones a <canvas> into an <img> nested inside the <foreignObject>
it serializes, and WebKit paints that SVG before the nested image has decoded,
so the first capture of a node holding a canvas comes back blank.
captureCanvasBlocks rasterizes each block exactly once, which means that in
Safari every chart in an exported PDF is empty; only the KPI sparklines survive,
because they are inline SVG rather than Vega's canvas renderer.

Probe once per capture with a tiny canvas and, where it comes back blank,
capture canvas-backed blocks twice and discard the first result. Probing rather
than matching the user agent keeps the extra pass off the browsers that do not
need it, and lets the workaround retire itself once WebKit changes.
paginate scaled the capture up to the page content width, so a phone-width
canvas was inflated by about 40%. That pushed rows past the page height, which
sliced whole charts across pages and left most of each following page empty.

Captures narrower than the page now keep their size and are centred.
The off-screen export render took its width from the width the dashboard
happened to occupy on screen, so the same canvas produced a different document
depending on the window it was exported from, and a phone produced a narrow
capture stacked into a single column.

Render it at the canvas's max_width instead.
@nishantmonu51 nishantmonu51 added Type:Bug Something isn't working Area:Dashboard Size:M Medium change: 100-499 lines labels Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area:Dashboard Size:M Medium change: 100-499 lines Type:Bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants