SVG to CSS Background-Image Converter

Convert SVG code to a CSS background-image data URI. Choose from UTF-8 percent-encoded, Base64, or inline output.

Last reviewed: April 2026

New to this tool? Click here for instructions

Input SVG
CSS Output
Single / no-repeat
Tiled preview
Paste SVG code above to generate CSS.

Paste any SVG markup and instantly generate a CSS background-image: url('data:image/svg+xml;utf8,...') rule that you can drop into a stylesheet — no HTTP request, no sprite sheet, no extra file. The tool emits both UTF-8 percent-encoded and Base64 forms, reports the byte-size difference between them, and previews the result at any pixel size with single and tiled rendering side-by-side.

What This Tool Does

This converter takes raw SVG markup — the kind you would normally save to an .svg file or paste into an inline <svg> element — and rewrites it as a CSS-ready data URI suitable for use inside background-image, list-style-image, border-image, or any other CSS property that accepts a <url> value. The output is a complete CSS rule block, including background-size and background-repeat hints derived from the SVG's viewBox dimensions, ready to paste into a stylesheet without further editing.

Three encoding modes are available. The default mode is UTF-8 percent-encoding, which escapes only the small set of characters that conflict with CSS or URI syntax — #, <, >, ", ', %, and whitespace — and leaves the rest of the SVG as readable ASCII. The Base64 mode wraps the entire SVG byte sequence in a standard btoa call, producing a longer but visually opaque payload. The Inline (no encode) mode performs minimal whitespace cleanup only and trusts the caller to handle CSS escaping manually — useful when you want to inspect the raw byte cost of a payload before deciding on an encoding strategy.

Everything runs entirely in your browser. The SVG markup you paste never leaves your local session — no upload, no server processing, no telemetry. The tool depends on built-in browser APIs (encodeURIComponent, btoa, Blob) plus a small amount of glue code for the live preview pane.

How to Use It

The workflow has four steps, none of which require leaving the page. The result is a CSS snippet you can paste directly into your stylesheet.

1. Paste Your SVG Into the Input Pane

Paste any well-formed SVG markup into the left-hand input pane. The SVG should include an xmlns="http://www.w3.org/2000/svg" attribute on the root element — if your markup omits the namespace, the tool automatically injects it, but the SVG will not render as a CSS background without it. A viewBox attribute is also strongly recommended; without one, the SVG cannot scale proportionally inside a background-size declaration. You can use the Try Example button to pre-fill a simple 24x24 chevron icon if you just want to see how the tool behaves.

2. Choose an Encoding Mode

The three option chips above the input pane control the output encoding. UTF-8 percent-encoded is the default and is the right choice for almost every small-to-medium SVG icon. Base64 is a fallback for SVGs that contain unusual binary content or large CDATA blocks. Inline is rarely the right answer for production CSS — it skips the URI escaping that browsers require for special characters — but it is useful for inspecting the unencoded payload size as a baseline against which to compare the encoded forms.

3. Adjust the Preview Controls

Three preview controls below the output pane let you simulate how the SVG will actually render in a real stylesheet. The size slider sets the background-size value in pixels, ranging from 16px (typical icon) to 200px (large hero icon or pattern). The repeat selector toggles between no-repeat (single positioned icon) and the various tiling modes — pick repeat to see how the SVG behaves as a wallpaper pattern, repeat-x for a horizontal divider strip, or space for evenly-distributed tiling without distortion. The background color picker sets the surface color behind the SVG, which is useful for checking that transparent regions composite correctly.

4. Copy or Download the CSS Rule

Once the preview matches what you want, click Copy CSS to copy the full rule block to your clipboard, or Download .css to save it as a standalone svg-background.css file. The output includes a class selector, the background-image property with the encoded data URI, and the matching background-size, background-repeat, and explicit width/height declarations.

Worked Example: Converting a Chevron-Down Icon

To make the encoding-size tradeoff concrete, here is a typical small icon — a 24x24 pixel chevron-down used for collapse/expand UI controls — rendered through each encoding mode with byte-level measurements.

The Source SVG

Start with a minimal 192-byte SVG. The icon is a single path element drawing a downward-pointing chevron, with explicit fill="#1f2937" for a dark slate gray:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="#1f2937" d="M12 16l-6-6h12l-6 6z"/></svg>

UTF-8 Percent-Encoded Output (Recommended)

Running the SVG through UTF-8 percent-encoding produces approximately 248 bytes of CSS value. Only the characters that conflict with URI syntax are escaped: %20 for space, %23 for the # in the color literal, %22 for double quotes (or ' swap), and the angle brackets for SVG tags. The full CSS rule is:

.chevron-down {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='%231f2937' d='M12 16l-6-6h12l-6 6z'/%3E%3C/svg%3E");
  background-size: 24px 24px;
  background-repeat: no-repeat;
  background-position: center;
  width: 24px;
  height: 24px;
}

The encoded payload remains visually inspectable — you can spot the SVG tag boundaries and the path commands at a glance — and the repeated SVG keywords (svg, xmlns, viewBox, path) compress extremely well under Gzip when this CSS rule lives in a larger stylesheet.

Base64 Output

The same SVG encoded as Base64 produces approximately 272 bytes — about 24 bytes larger than the percent-encoded form, and significantly less Gzip-friendly because the Base64 alphabet has no repeated byte sequences:

.chevron-down {
  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48cGF0aCBmaWxsPSIjMWYyOTM3IiBkPSJNMTIgMTZsLTYtNmgxMmwtNiA2eiIvPjwvc3ZnPg==");
  background-size: 24px 24px;
}

Byte-Size Comparison

For this 192-byte source SVG, UTF-8 percent-encoding wins by roughly 10% raw and by a much larger margin after Gzip compression. The gap widens as the SVG grows — a 1 KB icon shows a 33% raw advantage for percent-encoding because Base64's overhead is constant at four output bytes per three input bytes. The crossover point where Base64 starts to win is roughly when the SVG contains more than 60% non-ASCII bytes (embedded binary, unusual Unicode glyphs), which is uncommon for vector iconography. The takeaway: default to UTF-8 percent-encoding for icons, switch to Base64 only when the SVG payload contains substantial embedded binary data.

Common Use Cases

List Bullet Replacement

The most familiar use case is replacing the default disc bullet on a <ul> with a custom SVG glyph — a checkmark, chevron, star, or branded icon. Standard list-style-image works but offers no control over size or positioning. The recommended pattern uses ::before on each <li>:

ul.custom-bullets li::before {
  content: "";
  display: inline-block;
  width: 16px;
  height: 16px;
  background-image: url("data:image/svg+xml,%3Csvg...%3E");
  background-size: 16px 16px;
  background-repeat: no-repeat;
  margin-right: 8px;
  vertical-align: middle;
}

Because ::before cannot contain HTML, the SVG must come in via background-image rather than an inline <svg> element. Inlining the data URI avoids the HTTP request the browser would otherwise need for an external bullet icon, which is meaningful on lists with many items.

Custom Form Controls

Native HTML form controls — checkboxes, radio buttons, select dropdowns — render with browser-default UI that is difficult to style consistently across operating systems. The standard pattern hides the native control with appearance: none, then renders a ::before pseudo-element with an SVG background that you control completely. The unchecked state shows an empty box; the :checked state swaps the background to a check-mark SVG. Both SVGs travel inline with the CSS, eliminating the request-latency variability that would otherwise affect form interaction feedback.

Button Icons Without a Sprite Sheet

Traditional icon delivery uses an SVG sprite sheet — a single file containing many <symbol> definitions referenced via <use href="#icon-name"/>. Sprite sheets work well, but they introduce a hard dependency: every page using any icon must load the sprite file, and tooling needs to know which icons are used to support tree-shaking. Inline data URIs bypass the sprite-sheet pipeline entirely. You can define a CSS custom property for each icon and reference it by name from the relevant button class, and your bundler will inline only the icons actually referenced.

CSS-Only Icon Systems for Static Sites

For static sites with no JavaScript runtime — landing pages, documentation sites, marketing pages — an entire icon library can live in a single CSS file as custom-property definitions. Each icon becomes a CSS variable like --icon-cart: url('data:image/svg+xml,...'), and consuming elements reference the variable: background-image: var(--icon-cart). This eliminates both the runtime JavaScript that some icon libraries require and the separate HTTP requests for individual icon files. The cost is the data URI's lack of independent caching — but for a static-site stylesheet that itself caches well, that tradeoff is usually fine.

Edge Cases and Gotchas

Characters That Must Be Encoded

Five characters must always be percent-encoded inside a CSS data URI, because each conflicts with either CSS-value syntax or URI syntax. The # character (used in hex color literals) must become %23 — leaving a raw # in the data URI causes the CSS parser to treat the rest of the URI as a URL fragment and discard it. The < and > characters (used in SVG tags) become %3C and %3E in strict URI encoding, though most browsers tolerate them unescaped. The " character (used in attribute values) becomes %22, or you can switch to single quotes inside the SVG to avoid the issue. The ' character (used by some SVG generators) becomes %27. The % character itself must always be encoded as %25, because it is the escape introducer in percent-encoding and cannot appear literally. The tool handles all of these automatically — this list matters primarily when you are hand-editing a generated data URI.

Why Base64 Wastes Bytes on Small SVGs

Base64 encoding always emits four ASCII characters for every three bytes of input. That ratio gives Base64 a constant 33% size overhead, regardless of the input's content. For a 200-byte SVG, that overhead amounts to roughly 67 extra bytes. Percent-encoding, by contrast, only adds three bytes per escaped character, and only a handful of characters in a typical SVG need escaping at all. The math heavily favors percent-encoding for any SVG that is predominantly ASCII text — which describes essentially every hand-authored or tool-exported SVG icon. The gap narrows for SVGs with extensive embedded binary content (rasterized image data inside an SVG, large CDATA blocks), where percent-encoding ends up escaping nearly every byte.

Safari Charset Quirk

Historically, Safari required the explicit MIME charset parameter for percent-encoded SVG data URIs to render correctly. The minimal form is data:image/svg+xml;charset=utf-8, — note the ;charset=utf-8 between the MIME type and the comma. Chrome and Firefox have always tolerated the omission and assumed UTF-8 by default, but older Safari versions (anything before Safari 14, roughly) silently fail to render data URIs without an explicit charset declaration. Modern Safari (16+) has relaxed this requirement, so newer sites can skip the charset parameter, but adding it costs only 13 bytes per data URI and guarantees compatibility with older WebKit-based browsers and the various WebView shells (older iOS apps, in-app browsers, embedded webviews). When in doubt, include the charset.

The xmlns Attribute Is Mandatory

An SVG without the xmlns="http://www.w3.org/2000/svg" attribute on its root element will not render as a data URI background, even though it might render correctly when inlined as an HTML element. The reason: when an SVG appears inside an HTML document, the HTML parser implicitly establishes the SVG namespace context, so the explicit xmlns is redundant. When the same SVG is loaded via background-image, the browser parses it as a standalone XML document with no implicit namespace context — and SVG elements without the namespace are treated as generic XML elements with no rendering behavior. The tool automatically injects the namespace if your input is missing it, but if you ever hand-edit a data URI and the icon mysteriously stops rendering, this is the first thing to check.

currentColor Does Not Inherit Into Data URIs

One of the most common surprises: fill="currentColor" inside an SVG data URI does not inherit the CSS color property from the host element. This is a fundamental consequence of how the browser treats data URI documents — each is a separate document with its own cascade boundary, and the CSS color property does not propagate across that boundary. The workarounds are covered in the FAQ below; the short version is either hardcode the color in the SVG or use CSS mask-image with a solid background-color to recolor.

Behind the Scenes: Data URI Internals

The Data URI Scheme (RFC 2397)

The data: URI scheme is specified in RFC 2397 (Masinter, 1998). The full grammar is: data:[<mediatype>][;base64],<data>. The MIME type is optional and defaults to text/plain;charset=US-ASCII when absent. The ;base64 flag, when present, signals that the data portion is Base64-encoded rather than percent-encoded; when absent, the data is treated as a URL-encoded sequence per RFC 3986 percent-encoding rules. This grammar is intentionally minimal — it inlines an entire small resource directly into a URI string, with no separate transport step. The standard explicitly anticipates the use case the tool here addresses: embedding small images directly in HTML or CSS to avoid round-trip requests.

The image/svg+xml MIME Type

SVG documents are served with the image/svg+xml MIME type, registered with IANA and defined in the SVG 1.1 specification. The +xml suffix is part of the structured syntax suffix convention from RFC 6839 — it tells consumers that the resource is an XML document underneath, which lets generic XML tooling parse it without media-type-specific knowledge. When a data URI declares image/svg+xml, the browser invokes its SVG rendering pipeline rather than its raster image decoder, which is what makes the SVG render as a vector at any scale.

URI Percent-Encoding (RFC 3986)

Percent-encoding is defined in RFC 3986 (Berners-Lee, Fielding, Masinter, 2005), the master URI specification. The rule is straightforward: any octet that cannot appear literally in the URI grammar must be encoded as %XX, where XX is the uppercase hexadecimal representation of the octet's value. Reserved characters (:, /, ?, #, [, ], @) can appear literally in some positions but must be encoded in others. Unreserved characters (alphanumerics plus - . _ ~) always appear literally. The set of characters the tool actually needs to encode for SVG content is small in practice — most SVG markup consists of unreserved characters that pass through encoding unchanged.

Why background-image Treats Data URIs Differently From img src

An SVG loaded via <img src="data:..."> behaves slightly differently from the same SVG loaded via background-image: url(data:...) — and Safari historically exposed the most pronounced differences. In the <img> case, the browser routes the SVG through its image-decoding pipeline and applies image-specific security restrictions: scripts and external references inside the SVG are disabled, and the SVG is rendered with the same security context as any other replaced element. In the background-image case, the SVG is treated similarly but the layout context is purely decorative — the SVG can never receive events, never participate in the accessibility tree, and never be selected. For most use cases this distinction is invisible, but if you find an SVG that renders in an <img> but not as a background (or vice versa), the difference is almost always a security restriction being applied differently between the two pipelines.

Comparison: This Tool vs. SVGOMG, Base64-Encode.com, and URL-Encoder by Yoksel

Several other tools handle adjacent parts of the SVG-to-CSS workflow. Each is optimized for a slightly different job, and the right tool depends on what you are starting from.

SVGOMG (jakearchibald.github.io/svgomg)

SVGOMG is an SVG optimizer, not an encoder. It runs the SVGO library in the browser to strip unused attributes, collapse redundant transforms, round path coordinates, and remove editor metadata that Illustrator or Figma adds. The output is still an SVG file, just smaller. SVGOMG is the right starting point when your SVG came out of a design tool and contains a lot of editor cruft — a typical 5 KB Figma export can shrink to under 1 KB through SVGOMG without any visible quality loss. Run SVGOMG first to minimize the SVG, then run the optimized result through this tool to encode it as a data URI. The two tools compose well.

Base64-Encode.com

Base64-Encode.com is a generic Base64 encoder that handles any input — text, binary, or SVG. It is not SVG-aware: it does not know that percent-encoding is usually a better choice for SVGs, it does not produce the surrounding CSS rule, and it does not preview the result. Use it only when you specifically need Base64 output and you want to avoid the SVG-specific defaults of a tool like this one. For ordinary CSS-icon work, the SVG-specialized encoder produces better output with less manual editing.

URL-Encoder for SVG by Yoksel (yoksel.github.io/url-encoder)

Yoksel's URL-Encoder is the closest direct comparison to this tool — it is also SVG-specific and also produces percent-encoded data URIs. It has been a reference implementation in the SVG-CSS community for years. The differences are tooling-level rather than algorithmic: this tool adds a live tile preview, an explicit Base64 fallback mode, byte-size measurement comparing the encoded output to the original SVG, and a complete CSS rule output rather than just the URI string. Yoksel's tool is excellent and has a long track record; if you already use it and the workflow fits, there is no reason to switch. If you want the additional live-preview and CSS-rule scaffolding, this tool covers that ground.

Related Tools on ThisDevTool

The data-URI workflow typically connects to a small set of adjacent tools. The SVG Optimizer handles the cleanup step before encoding — strip editor metadata, collapse paths, round coordinates — so the resulting data URI is as small as possible. The SVG Path Editor lets you tweak path data directly when an exported icon needs a precision adjustment that would be awkward in a design tool.

For Base64-specific workflows outside SVG, the Base64 Encoder/Decoder handles arbitrary text and binary payloads with the same encoding algorithm this tool uses internally. The CSS Gradient Generator covers the related case of building visually rich CSS backgrounds without an image at all — for simple geometric patterns, CSS gradients often beat encoded SVGs on both byte count and render performance. The Box Shadow Editor rounds out the decorative-CSS toolkit.

Frequently Asked Questions

Why use a data URI instead of an external SVG file?

A data URI inlines the SVG bytes directly into the CSS rule, which eliminates the separate HTTP request the browser would otherwise make to fetch an external .svg file. For small icons (under about 2 KB), the round-trip cost — DNS, connection setup, TLS handshake on cold visits, and the request itself — typically dominates the actual transfer time, so inlining is faster. Inlining also guarantees the icon is available the moment the stylesheet is parsed, with no chance of a delayed-paint flash. The tradeoff: inlined data URIs can no longer be cached independently of the CSS file, so updating an icon invalidates every stylesheet that uses it.

Should I use UTF-8 percent-encoding or Base64 for SVG data URIs?

For small SVG icons, UTF-8 percent-encoding produces a smaller and more Gzip-friendly result than Base64. Base64 always inflates byte length by approximately 33% because it encodes three input bytes as four ASCII characters. Percent-encoding only escapes the small set of characters that conflict with URI syntax (#, <, >, ", ', %, space) and leaves the rest of the SVG as readable ASCII. A 200-byte chevron icon ends up around 280 bytes in percent-encoded form versus 270 bytes in Base64, but the percent-encoded form compresses much better under Gzip because its repeated SVG keywords (svg, viewBox, path) stay intact. Reserve Base64 for binary-heavy SVGs that contain embedded raster images or extensive CDATA sections.

Can I use currentColor in a CSS-embedded SVG data URI?

No — and this is one of the most common surprises developers hit. The currentColor keyword inherits the value of the CSS color property from the element rendering the SVG, but a data URI loaded via background-image is treated as a separate document by the browser. The CSS color cascade does not extend across that document boundary, so currentColor inside the data URI resolves to its initial value (black) every time. The standard workarounds are: hardcode the color in the SVG and generate multiple variants (one per theme color), use a CSS mask-image with a solid background-color, or use the SVG as a <use> reference to an inline <symbol> defined in your HTML — the inline-symbol pattern preserves currentColor inheritance because it stays within the document's CSS cascade.

What is the size limit for data URIs in CSS?

There is no hard size limit defined by the CSS or data URI specs themselves — browsers will parse arbitrarily large data URIs in a stylesheet. The practical ceilings come from secondary effects: data URIs cannot be cached independently of the CSS file that contains them, so a 50 KB inlined SVG forces the entire stylesheet to be re-downloaded whenever the icon changes. Most engineering teams cap inlined SVG data URIs at 2-4 KB and treat anything larger as an external file. For SVGs above 10 KB, an external file with HTTP caching almost always beats an inlined data URI for repeat visits. Lighthouse will not penalize data URIs of reasonable size, but it will flag a stylesheet larger than 50 KB.

Why does my SVG data URI break in Safari but work in Chrome?

Safari historically requires the explicit MIME charset parameter — image/svg+xml;charset=utf-8 — before it parses a percent-encoded SVG data URI. Chrome and Firefox tolerate the omission and default to UTF-8 charset detection, but older Safari versions render the SVG as a broken-image icon when charset is absent. If your data URI works in Chrome but breaks in Safari, the fix is almost always to add ;charset=utf-8 immediately after the MIME type and before the comma. Modern Safari (16+) has relaxed this requirement, but the explicit charset is still the most compatible form and costs only 13 extra bytes per URI.

How do I make a data URI SVG change color on :hover?

Because currentColor does not inherit into a data URI, the standard approach is to pre-generate one data URI per color state and swap the background-image on :hover. Use CSS custom properties to store the URIs once: --icon-default and --icon-hover, then reference them with background-image: var(--icon-default) and background-image: var(--icon-hover) inside the :hover rule. Two alternative patterns avoid the dual-URI problem entirely: (1) Apply the SVG with mask-image instead of background-image, then use background-color to recolor — mask-image keeps the alpha channel but discards the SVG's fill colors, so background-color shows through; or (2) use CSS filter properties like filter: brightness(0) invert(1) to tint the existing data URI without generating a new one. The mask-image approach is generally cleanest for single-color icons.

Are data URIs cached by the browser?

Yes, but only as part of the parent resource — the CSS or HTML file that contains them. Data URIs do not have their own URL and cannot appear in the browser's cache index independently. This is a meaningful tradeoff: a single external SVG file referenced from multiple pages is downloaded once and cached for every subsequent page load, while the same SVG inlined into multiple CSS files must be downloaded inside each separate stylesheet. For an icon used on every page in a single site-wide stylesheet, inlining is fine because that stylesheet caches efficiently. For icons reused across multiple separately-cached CSS files, an external SVG is almost always cheaper at scale. Browser memory caches do dedupe identical data URI strings within a single page session, so reusing the same data URI in 50 CSS rules does not allocate 50 separate decoded SVG documents.

Will Lighthouse penalize me for using inline SVG data URIs?

Lighthouse does not flag inline SVG data URIs as a category-level issue, but a few related audits can trigger if the inlining is excessive. The Reduce unused CSS audit fires if the data URI ends up in the critical-path stylesheet but the icon is only used on a non-critical page. The Avoid serving legacy JavaScript audit is unaffected because data URIs are inert payloads. The Eliminate render-blocking resources audit may surface if a single CSS file balloons past 100 KB because of many inlined icons. As a rule of thumb: each inlined SVG should pay its way — replacing a small HTTP request with an inline payload — and the total inlined budget per stylesheet should stay under 20 KB compressed. Above that threshold, switching to an external SVG sprite sheet or a font-icon strategy generally yields better Lighthouse Performance scores.

Quick reference

SVG to CSS Background-Image Converter Quick Reference
SVG Attribute CSS Property Value Example Notes
fill background-color #4A90E2 Controls SVG shape color
stroke border 2px solid #FF6B6B Applies to vector outlines
transform transform translate(10px, 20px) Preserves SVG animation behavior
viewBox background-size 100% 100% Ensures responsive scaling
opacity opacity 0.8 Affects entire SVG element
mask mask-image url(data:image/svg+xml;...) Requires data URI encoding