How to use an SVG background in CSS
External file, data URI, or inline markup — when each one is right.
Updated · 5 min read
There are exactly three correct ways to use an SVG as a CSS background: reference it as an
external file, embed it as a data URI, or skip
background-image entirely and inline the markup behind your content. They
differ in caching, requests, and whether you can restyle the SVG — pick by situation, not by habit.
1 — External file: the default
Save the SVG and reference it like any image:
.hero {
background-image: url('/backgrounds/waves.svg');
background-size: cover;
} One HTTP request, then it's cached across every page that uses it. This is the right choice for shared, recurring backgrounds — site-wide heroes, section dividers, patterns. The only real cost is that first request, and the only real gotcha is that the browser can't restyle the file's internals: colors are baked into the SVG.
2 — Data URI: zero requests, with an encoding rule
The whole SVG travels inside the stylesheet:
.card {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' ...%3E...%3C/svg%3E");
}
No extra request, renders on first paint — ideal for small, one-off decorations. The rule that trips
everyone: URL-encode the markup. At minimum # must become %23
(hex colors break otherwise, silently), and </> become
%3C/%3E. Base64 also works but is ~33% larger and unreadable in DevTools; encoded
plain text is the better default. Skip data URIs for big SVGs — they bloat the stylesheet and can't be cached
independently of it.
3 — Inline markup: when CSS should restyle it
Put the <svg> element directly in the HTML, absolutely positioned behind content with
z-index. It's not a "background" in the CSS sense, but it's the only approach where CSS can
reach inside — recolor paths with fill: currentColor, animate individual shapes, react to
themes and hover states. Use it for backgrounds that must adapt (dark mode, brand theming) or animate
per-element. Cost: the markup weighs on every page it appears in, and screen readers should get
aria-hidden="true" on decorative inline SVGs.
Which one, in one line each
- Shared/recurring background: external file — cached once, used everywhere.
- Small one-off decoration: data URI — zero requests, just encode it properly.
- Needs restyling or animation from CSS: inline markup.
Every background our generators export — mesh gradients, waves, blobs, patterns — comes out ready for any of the three: as a downloadable .svg file, as pre-encoded data-URI CSS you paste straight in, or as raw SVG markup.