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.

ValueResult
containAs large as possible with the whole image visible. Empty space may remain
coverLarge enough to cover the whole element. Parts of the image may be cut off
200px auto200 pixels wide, with the height worked out from the image’s proportions
100% 100%The image area is the whole element
40px 40pxA 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 width and height: 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 with contain.

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 %3C and %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 fill or color on 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:

  1. Write the colour into a data URI. Each colour needs its own URI, for example one for the normal state and one for :hover.
  2. Use the SVG as a mask. The SVG supplies the shape and background-color supplies the colour, which can then change freely. Changing SVG colour with CSS has the code.
  3. Edit the file. Change the fill values 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 seeCauseFix
Nothing showsThe element has no height: an empty <div> is zero pixels tallGive it content, height, min-height or padding
Nothing showsThe path is wrong. In a stylesheet, a relative path starts from the stylesheet’s folder, not the page’sCorrect the path, or start it with /
Nothing showsThe SVG file lacks xmlns="http://www.w3.org/2000/svg"Add it to the root <svg>
A data URI shows nothingAn unescaped #, or quotes that close the url("...") earlyWrite %23; use single quotes inside the SVG
The image is squashedThe file has no viewBoxAdd viewBox="0 0 W H" using its width and height
It will not stretch to fillAn SVG with a viewBox keeps its proportionspreserveAspectRatio="none" in the file
The colour will not changePage CSS does not reach a background imageA mask, or a data URI in the new colour
Text in the SVG is in the wrong fontA background SVG cannot load web fontsConvert 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.