Skip to tool
ecech.
💻 Developer & Code

Free SVG to CSS Background Data URI Encoder That Beats Base64 on Size

Base64 makes an SVG 33% bigger and kills gzip. Percent-encoding only what CSS actually chokes on is smaller, still valid, and still readable.

Original SVG

0 B

Percent-encoded

0 B

Base64

0 B

Preview

on white

on dark

tiled

The CSS


What got escaped

Advertisement

How the calculation works

Same icon, two encodings Raw SVG 185 bytes Percent-encoded 218 bytes Only < > # " and a few others are escaped. Still human-readable, still compresses. Base64 274 bytes 33% larger by definition, unreadable, and gzip can find almost nothing to compress.

How to Use This Tool

Putting an SVG straight into CSS as a background-image removes an HTTP request and stops the icon flashing in late. The question is how to encode it, and the popular answer is the wrong one.

Do not use base64

Base64 represents three bytes with four characters, so it is 33% larger by definition — before you have gained anything. Worse, it destroys compressibility: SVG is text full of repeated substrings like stroke-width and path d=, which gzip and brotli compress beautifully, and base64 turns that into high-entropy noise they can barely touch. On a stylesheet with a dozen inlined icons the compressed difference is substantial.

The alternative is to percent-encode only the characters CSS actually cannot handle. That is a short list: <, >, #, %, the quote character you are not using as the delimiter, and newlines. Everything else — letters, digits, spaces, slashes, equals signs — can stay as it is. The result is bigger than the raw SVG but smaller than base64, and you can still read it, which matters the day you need to change a colour without regenerating anything.

The entire escape list. Everything else can stay as it is. <→ %3C >→ %3E #→ %23 %→ %25 "→ ' newline→ removed everything else — left alone The # is the important one: in a URL it starts a fragment, so an unescaped fill="#2b7fff" truncates the whole image at that point. This is the single most common cause of "my inline SVG works in the file but not in CSS".
Swapping double quotes for single quotes inside the SVG lets you wrap the URI in double quotes without escaping anything.

The hash character will catch you out

If your SVG contains fill="#2b7fff" and you paste it into CSS unescaped, everything after the # is treated as a URL fragment and the image silently fails. No console error, no broken image icon — just nothing. This is the single most common reason an inline SVG works when opened as a file and not when used as a CSS background.

The xmlns attribute is not optional here

Inside an HTML document a browser will forgive a missing xmlns, because it already knows it is parsing HTML. A data URI is parsed as a standalone XML document, so without xmlns="http://www.w3.org/2000/svg" it fails to render entirely. Editors like Illustrator usually include it; hand-written and heavily optimised SVGs often do not. The tool adds it if it is missing.

When to inline and when not to

Inline small, decorative, unchanging things: icons, checkmarks, chevrons, subtle background patterns. Under about 2 KB the saved request is worth more than the added stylesheet weight.

Do not inline large illustrations. They bloat the stylesheet, which is render-blocking, so a 40 KB inlined graphic delays first paint for the entire page rather than loading alongside it. Keep those as separate files where the browser can fetch them in parallel and cache them independently.

Recolouring

A data URI cannot inherit currentColor — the SVG is a separate document and knows nothing about your CSS. If you need one icon in several colours, either generate one URI per colour, or use mask-image instead of background-image and set background-color, which lets a single monochrome shape take any colour you like.

Advertisement

Frequently Asked Questions

Should I use base64 or percent-encoding for SVG in CSS?
Percent-encoding, almost always. Base64 is 33% larger by definition and turns compressible text into high-entropy noise that gzip and brotli can barely shrink, so the gap after compression is even wider than the raw numbers suggest. Percent-encoding also stays readable, which matters when you need to change one colour later.
Why does my SVG data URI not show anything?
Two overwhelmingly likely causes. First, an unescaped # from a hex colour — in a URL that starts a fragment, so everything after it is discarded and the image fails silently. Second, a missing xmlns attribute: a data URI is parsed as a standalone XML document and will not render without it, even though the same markup works fine inside HTML.
Which characters actually need escaping?
Only <, >, #, % and whichever quote character you are using as the delimiter, plus newlines. Everything else — letters, digits, spaces, slashes, equals signs, commas — is valid in a data URI as-is. Swapping the double quotes inside your SVG for single quotes lets you wrap the whole URI in double quotes without escaping any of them.
Can a data URI SVG use currentColor?
No. The SVG in a data URI is a separate document with no access to the CSS around it, so currentColor has nothing to resolve against. Either generate one URI per colour you need, or use mask-image with background-color instead, which lets a single monochrome shape be tinted freely.
How large can an inlined SVG reasonably be?
Roughly 2 KB is a sensible ceiling. Below that, saving an HTTP request usually wins. Above it you are adding weight to a render-blocking stylesheet, so a large inlined graphic delays first paint for the whole page instead of loading in parallel and being cached separately.
Does the xmlns attribute really matter?
In a data URI, yes, absolutely. Inside an HTML document the browser already knows it is in HTML and will infer the SVG namespace, but a data URI is parsed standalone as XML, where the namespace declaration is mandatory. This is why an SVG can display perfectly when opened directly and render nothing at all as a CSS background.
Is an inlined SVG cached by the browser?
Only as part of the stylesheet that contains it, not independently. That is the trade-off: you save a request, but the icon can no longer be cached separately or shared between pages that load different CSS. For a handful of small icons that is a good deal; for a large illustration used on one page, it is not.

Related tools in Developer & Code

Browse all Developer & Code tools
The Mac mini the ecech. site is built on, beside a handwritten note reading ecech.com.

Made by one person

ecech. is not a content farm. Every tool here is written and checked by hand, one at a time, by someone who wanted the tool to exist and could not find a version that showed its working.

No accounts and no sign-in, and nothing you type reaches a server — every calculation on this page runs inside your browser. The ads are served by Google and do set their own cookies, which is set out in full on the privacy page. More about the site.