Encoding SVG as a Data URI, and Why URL-Encoding Usually Wins

The Problem

I already had a little SVG base64 embedding sandbox — but it's a static demo: three example SVGs baked in as data URIs to show that the technique works and that scripts inside an <img>-embedded SVG are ignored. What it doesn't do is let you paste your SVG and get the string back. So this is the interactive counterpart: markup in, data URI out.

The Approach

You paste an <svg> and get a live preview (rendered through an actual <img> data URI, so what you see is exactly what you'd embed), both encodings side by side with their byte sizes, and ready-to-paste <img> and CSS background-image snippets. It fixes the two things that quietly break inline SVG: it adds the xmlns namespace if you left it off (without it the browser won't render the data URI at all), and it can strip comments and collapse whitespace first.

The SVG Data URI Encoder: markup input, a rendered sun preview on a checkerboard, a size table showing URL-encoded is smaller, and the two data URIs plus img and CSS snippets
Figure 1: A 541-byte sun becomes a 750-byte base64 URI or a 564-byte URL-encoded one — URL-encoding wins by 25%.

Base64 is the reflex; URL-encoding is usually smaller

Everyone reaches for base64 because it's the encoding you already know, but it's the wrong default for SVG. Base64 turns three bytes into four characters — a flat ~33% inflation — regardless of what's inside. SVG, though, is mostly plain ASCII (<path d="M0 0...">), and the alternative encoding just leaves that text alone and percent-escapes the handful of characters a URL can't carry. So data:image/svg+xml,… is almost always smaller than data:image/svg+xml;base64,…, and it has the bonus of staying human-readable and diffable in your CSS. The tool shows both sizes and flags the winner; for the example sun it's a 25% saving, and it grows with the proportion of markup to binary-ish content.

The encoding details worth knowing
  • The base64 path is UTF-8 safe: the markup is UTF-8-encoded before btoa, so an SVG with non-ASCII text doesn't throw or corrupt.
  • The URL-encoding uses the well-known minimal scheme: swap double quotes for single quotes (so the URI can live inside double quotes), collapse whitespace between tags, and percent-escape only %#()<>?[\]^`{|} and newlines. Everything else stays legible.
  • Scripts and event handlers inside the SVG are inert once it's loaded via <img> or CSS url() — the same safety property the sandbox demonstrates. Inline <svg> in the document itself is not sandboxed and can run script.
  • Inline the small stuff — icons, logos, one-off illustrations. A large SVG as a data URI bloats the file it lives in and doesn't cache separately; past a few KB, link it as a file instead.

It's the usual shape for these: one static file, vanilla JS, your markup persisted in localStorage and nothing leaving the browser. If you want a raster PNG or JPEG out of an SVG instead of a data URI, that's the SVG to JPEG/PNG renderer.

The tool: SVG Data URI Encoder.

References

  1. [1] MDN — Data URLs (the data: URI scheme and base64). developer.mozilla.org
  2. [2] The minimal SVG URL-encoding scheme popularized by Yoksel's “URL-encoder for SVG.”