How to use an SVG as a CSS background image
Set an SVG as a CSS background with background-image: url(), from a file or a data URI. How to size, repeat and recolour it, and why it may fail to show.
Published
To use an SVG as a CSS background, point background-image at the file: background-image: url("pattern.svg"). It behaves like a PNG or JPG background, except that it stays sharp at any size. A small SVG can also be written into the stylesheet itself as a data URI, which saves a request.
.hero {
background-image: url("waves.svg");
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
The same in one line:
.hero { background: url("waves.svg") no-repeat center / cover; }
In the shorthand, the size comes after the position, separated by a slash.
Setting the size
background-size decides how large the SVG is drawn.
| Value | Result |
|---|---|
contain | As large as possible with the whole image visible. Empty space may remain |
cover | Large enough to cover the whole element. Parts of the image may be cut off |
200px auto | 200 pixels wide, with the height worked out from the image’s proportions |
100% 100% | The image area is the whole element |
40px 40px | A tile of that size, repeated unless no-repeat is set |
With no background-size, the result depends on what the file says about itself:
- The SVG has
widthandheight: it is drawn at that size. - The SVG has only a
viewBox: it has proportions but no size, and is scaled to fit inside the element, as withcontain.
An SVG scales cleanly only if its root element has a viewBox. A file that has width and height but no viewBox is stretched to the size given without keeping its proportions. SVG viewBox explained shows how to add one.
Stretching an SVG to fill the element
background-size: 100% 100% squashes a PNG to fit. An SVG with a viewBox does not squash: it keeps its proportions inside that area and leaves bands at the sides or at top and bottom. For a shape that should stretch, such as a curved divider across the bottom of a section, add preserveAspectRatio="none" to the root <svg> element of the file:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 10" preserveAspectRatio="none">
<path d="M0 10 Q50 -10 100 10 Z" fill="teal"/>
</svg>
.section { background: url("curve.svg") no-repeat bottom / 100% 40px; }
The curve now spans the full width of the section at a fixed height of 40 pixels.
Repeating patterns
A background repeats in both directions unless told otherwise, so a small SVG tile makes a pattern. background-size sets the size of one tile:
.dots {
background-image: url("dot.svg");
background-size: 20px 20px;
}
Use background-repeat: repeat-x or repeat-y to repeat along one axis only.
Inlining the SVG as a data URI
A data URI puts the file’s contents where its address would go:
.dots {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Ccircle cx='5' cy='5' r='2' fill='%23c33'/%3E%3C/svg%3E");
background-size: 20px 20px;
}
This draws red dots 8 pixels across, one every 20 pixels, with no separate file. The rules that make it work:
- The SVG must have
xmlns="http://www.w3.org/2000/svg". Here it is a document of its own, not part of an HTML page. #must be written as%23. In a URL, everything after a bare#is treated as a fragment and dropped, which removes the rest of the SVG.<and>are best written as%3Cand%3E.- The quotes must not clash. Above, the URL sits in double quotes and the SVG uses single quotes.
Base64 is not needed. SVG is text, and the text form above is shorter than Base64, which adds a third to the size. SVG to Base64 and data URI makes the escaped form from any SVG, adding the xmlns a data URI needs if the code lacks it, and gives it ready wrapped as a background-image line.
Inline small images that appear on most pages. A large SVG in a stylesheet is downloaded with it every time the stylesheet changes, and cannot be cached on its own.
What a background SVG cannot do
The browser draws a background SVG as a finished picture, in the same restricted way as an SVG in an <img> tag.
- Page CSS cannot restyle it. No selector reaches inside, and
fillorcoloron the element has no effect on it. - Scripts in it do not run, and links in it cannot be clicked.
- It cannot load other files. A web font, stylesheet or picture that the SVG refers to is not fetched. Text falls back to a font on the device.
- It has no text alternative. Use it for decoration only. A picture that carries meaning belongs in the content: SVG in HTML compares the methods.
Styles written inside the SVG file itself still apply.
Changing the colour
Since page CSS cannot reach into the image, there are three ways to get a different colour:
- Write the colour into a data URI. Each colour needs its own URI, for example one for the normal state and one for
:hover. - Use the SVG as a mask. The SVG supplies the shape and
background-colorsupplies the colour, which can then change freely. Changing SVG colour with CSS has the code. - Edit the file. Change the
fillvalues and save a copy.
Several backgrounds
An element can have more than one background, listed with commas. The first is drawn on top:
.card {
background:
url("corner.svg") no-repeat top right / 80px,
url("paper.svg") repeat;
}
Common problems
| What you see | Cause | Fix |
|---|---|---|
| Nothing shows | The element has no height: an empty <div> is zero pixels tall | Give it content, height, min-height or padding |
| Nothing shows | The path is wrong. In a stylesheet, a relative path starts from the stylesheet’s folder, not the page’s | Correct the path, or start it with / |
| Nothing shows | The SVG file lacks xmlns="http://www.w3.org/2000/svg" | Add it to the root <svg> |
| A data URI shows nothing | An unescaped #, or quotes that close the url("...") early | Write %23; use single quotes inside the SVG |
| The image is squashed | The file has no viewBox | Add viewBox="0 0 W H" using its width and height |
| It will not stretch to fill | An SVG with a viewBox keeps its proportions | preserveAspectRatio="none" in the file |
| The colour will not change | Page CSS does not reach a background image | A mask, or a data URI in the new colour |
| Text in the SVG is in the wrong font | A background SVG cannot load web fonts | Convert the text to paths in a vector editor |
If the file itself may be at fault, open it in the SVG viewer: if it draws there and the viewer gives no warning about xmlns, the fault is in the CSS, the path or the file type the server sends. Why an SVG is not showing goes through the causes in order.
Questions
Should a background be an SVG or a PNG? SVG for flat shapes, patterns and curves: it is usually smaller and is sharp on every screen. PNG or JPG for photographs and painted textures.
Can the background be animated? An animation written inside the SVG file runs in current browsers. Page CSS can move or resize the whole background, with background-position for example, but cannot animate the shapes inside it.
Can page CSS style an SVG that sits behind content? Only if the SVG is inline in the HTML and positioned behind the content, with position: absolute and a lower z-index. It is then part of the page, not a CSS background.