ZYVOPMulti-Platform Sync
SeriesAI NewsWhy ZyVOPJoin Discord
LoginGet Started
ZYVOP
The Developer Publishing Hub
SeriesAI NewsPreview My BlogPrivacyTermsGuidelinesDMCACommunity
© 2026 ZyVOP
HomeArchitectureTiled Rasterization for Large DOM Captures
Architecture

Tiled Rasterization for Large DOM Captures

How SnapDOM captures one SVG and rasterizes it in bounded tiles—without allocating a full-page bitmap.

August 11, 2026•
4 min read
Tinchox5
Tinchox5
Originally published onsnapdom.dev
Senior Diplomat·
#web-performance#snapdom#JavaScript#canvas#dom-to-image#browser-api

A full-page DOM capture can succeed as SVG and still fail at the next step: turning that SVG into one enormous bitmap.

That is the problem SnapDOM addresses with tiled rasterization. The key is not merely to split the final canvas. It is to move the cut earlier—before the browser decodes the image.

TL;DR: Capture the DOM once, move a tile-sized window across the resulting SVG, and rasterize each window into its own canvas. You keep the requested resolution without ever allocating a full-page bitmap.

The hidden limit behind “full-page screenshots”

A full-page capture involves two very different artifacts:

  1. A serialized SVG containing a styled DOM clone inside <foreignObject>.
  2. The bitmap created when the browser decodes that SVG for Canvas, PNG, JPEG, or WebP.

The SVG can describe a document tens of thousands of pixels tall. The bitmap is where browsers usually push back. The practical ceiling depends on the browser and the machine, but oversized images can make img.decode() fail with an unhelpful EncodingError, or cause canvas allocation to fail afterward.

For a normal export, downscaling is a sensible fallback. But it is the wrong trade-off when the pixels themselves are the product: deep-zoom viewers, page renderers, print pipelines, tiled uploads, or visual archives should not lose resolution just because one giant bitmap is a poor container.

Cut the SVG, not the canvas

The obvious mosaic algorithm does not solve the problem:

  1. Render one giant canvas.
  2. Use drawImage() to cut it into smaller canvases.

By the time step two begins, the browser has already decoded and allocated the giant bitmap. The workaround arrives too late.

SnapDOM moves the crop earlier. With toCanvas({ crop }), SnapDOM rewrites the SVG root’s width, height, and viewBox so they describe only the requested window. Only then is the SVG passed to Image.decode().

The pipeline becomes:

Capture once → move the window → decode one small tile → consume it → repeat

The DOM is still cloned, styled, and serialized only once. Exporting ten tiles does not repeat font embedding, image inlining, or style collection ten times.

A practical tiling loop

The reliable crop bounds come from the capture metadata, not from reading the live element again.

async function tileCapture(capture, options, consume) {
  const {
    tileWidth = 2048,
    tileHeight = 2048,
    scale = 1,
    dpr = 1
  } = options

  const { contentX, contentY, w0, h0 } = capture.meta

  for (let y = 0, row = 0; y < h0; y += tileHeight, row++) {
    for (let x = 0, col = 0; x < w0; x += tileWidth, col++) {
      const width = Math.min(tileWidth, w0 - x)
      const height = Math.min(tileHeight, h0 - y)

      const crop = {
        x: contentX + x,
        y: contentY + y,
        width,
        height
      }

      const canvas = await capture.toCanvas({ crop, scale, dpr })
      await consume({ canvas, crop, row, col })
    }
  }
}

const capture = await snapdom(document.documentElement, { dpr: 1 })

await tileCapture(capture, {}, async ({ canvas, row, col }) => {
  const blob = await new Promise(resolve =>
    canvas.toBlob(resolve, 'image/png')
  )

  if (!blob) throw new Error('PNG encoding failed')

  try {
    await uploadTile(blob, { row, col })
  } finally {
    canvas.width = canvas.height = 0
  }
})

Exports on a single capture are queued, so the tiles rasterize in order instead of competing for decode and canvas memory. For genuinely large documents, encode, upload, or write each tile and release it before requesting the next one.

Geometry is part of the feature

Starting every mosaic at 0, 0 is not always correct. Root transforms, asymmetric shadows, outlines, and clipping can move the logical content inside the SVG viewBox.

SnapDOM exposes the final immutable geometry through result.meta:

Property What it measures Typical use
w0 / h0 Logical capture box Tile only the page content
contentX / contentY Content origin inside the viewBox Position the first content tile
vbW / vbH Complete serialized artifact Include shadows, bleed, and outer effects

Use contentX, contentY, w0, and h0 when you want the logical page. Use the complete viewBox when every pixel of transformed bleed or shadow must survive.

What tiling does—and does not—solve

Tiling removes the full-bitmap allocation from the equation. It does not turn DOM capture into a streaming renderer.

A few limits still matter:

  • Lazy or virtualized sections must exist in the DOM before capture.
  • Each tile, after scale × dpr, must still fit the browser’s raster limits.
  • Keeping every tile alive can consume the same total number of pixels in aggregate.
  • Stitching the tiles back into one giant canvas recreates the original problem.
  • SnapDOM still clones the full subtree, reads its styles, inlines assets, and stores the serialized SVG.
  • Each crop still parses the full <foreignObject> payload.

If the initial DOM walk is the bottleneck, clip is the complementary tool: it prunes off-window subtrees before styling and inlining, but requires a separate capture for every region. By contrast, crop reuses one frozen artifact, keeping fonts, images, animations, and live data consistent across all tiles.

Where tile windows are useful

The original use case was document export, where a tall capture naturally becomes PDF pages. The same mechanism works well for:

  • Deep-zoom or map-style viewers
  • Poster and large-format printing
  • Zoomable archives
  • Multipart uploads
  • Custom SnapDOM exporters and plugins

The claim is intentionally narrower than “unlimited screenshots.” One stable DOM snapshot becomes a sequence of bounded raster jobs. When every tile fits, the document no longer needs a global downscale.

Try the interactive mosaic

The original SnapDOM article includes a live demo that captures a 640 × 2,400 px report once and reconstructs it from ten independent canvases.

Open the interactive demo and full technical article →

You can also explore the Canvas crop API or view SnapDOM on GitHub.


Originally published by Zumerlab on the SnapDOM blog. This adapted version links back to the canonical article and interactive demo.

Comments (0)

Join the discussion by logging into your account.

No comments yet. Be the first to comment!

Tinchox5
Tinchox5

Senior Diplomat

Tech Diplomat

Subscribe to Tinchox5's Newsletter

Direct email dispatches when new stories are published. Zero algorithms.

Tinchox5
Like
Love
Clap
Fire
Party
Wow

Trending on ZyVOP

Ollaya Runs TypeSafe-Style Decision Models on Your Own Machine

Ollaya runs fast, calibrated decision models on your own hardware instead of a hosted API call, positioning itself against TypeSafe's closed Jev. Its speed and calibration claims are real, but they come from three separate benchmarks run by different people on different test sets.

Samod Alex
Samod Alex·
7 minSep 26

Architecture Case Study: Migrating a Developer SaaS from Serverless to a $10 VPS with Docker

Serverless platforms like Vercel and AWS Lambda are the default choice for modern web applications.

Sanju Singh
Sanju Singh·
8 minSep 26

Pi‑warden: Using Jev to Block Destructive Commands in 48 Hours

Jev, a decision‑only AI model released on September 15 2026, was quickly adopted by developers: pi‑warden, built within 48 hours, blocked 42 destructive commands out of 17,000 calls with an 88 % hold‑

Lê Đức Minh
Lê Đức Minh·
4 minSep 24

Unlocking Background Automation: Wrapping IBM Bob Shell into a Headless REST Service

Building a ‘Bob’ headless agent! Introduction When building developer tools and...

Alain Airom (Ayrom)
Alain Airom (Ayrom)·
8 minSep 25

Uint8Array toBase64 and toHex: Stop Round-Tripping Bytes Through btoa

JavaScript can finally turn bytes into base64 and hex (and back) without the String.fromCharCode and btoa dance. Here's how Uint8Array's new encoding methods work and where they replace the helpers you've been copy-pasting.

Danny Holloran
Danny Holloran·
4 minSep 25