Scaling of SVG backgrounds

This article is in need of a technical review.

Given the flexibility of SVG images, there's a lot to keep in mind when using them as background images with the background-image property, and even more to keep in mind when also scaling them using the background-size property. This article describes how scaling of SVG images is handled when using these properties.

The algorithm, in summary

The algorithm can for the most part be summarized by these four rules. There are some edge cases that aren't covered by these rules, but this covers the majority of cases.

  1. If background-size specifies a fixed dimension (that is, percentages and relative units are fixed by their context), that dimension wins.
  2. If the image has an intrinsic ratio (that is, its width:height ratio is constant, such as 16:9, 4:3, 2.39:1, 1:1, and so forth), the rendered size preserves that ratio.
  3. If the image specifies a size, and the size isn't modified by constrain or cover, that specified size wins.
  4. If none of the above cases are met, the image is rendered at the same size as the background area.

It's worth noting that the sizing algorithm only cares about the image's dimensions and proportions, or lack thereof. An SVG image with fixed dimensions will be treated just like a raster image of the same size.

Source image examples

Before diving in to look at the results of using different kinds of source images and seeing how they look when used with background-size, it would be helpful to look at a few example source images that have different dimensions and sizing settings.

In each case, we show what the source image looks like rendered in a 150x150 box, and provide a link to the SVG source.

Dimensionless and proportionless

This image is both dimensionless and proportionless. It doesn't care what size it is, nor does it care about remaining at a particular aspect ratio. This would make a good gradient desktop background that would work regardless of your screen size and its aspect ratio.

no-dimensions-or-ratio.png

SVG source

One specified dimension and proportionless

This image specifies a width of 100 pixels but no height or intrinsic ratio. This is, basically, a thin strip of wallpaper that could be stretched across the entire height of a block.

100px-wide-no-height-or-ratio.png

SVG source

One specified dimension with intrinsic ratio

This image specifies a 100 pixel height but no width. It also specifies an intrinsic aspect ratio of 3:4. This ensures that its width:height ratio is always 3:4, unless it's deliberately scaled to a disproportionate size (that is, by explicitly specifying both width and height that aren't of that ratio).

This is very much like specifying a specific width and height, since once you have one dimension and a ratio, the other dimension is implied, but it's still a useful example.

100px-height-3x4-ratio.png

SVG source

No width or height with intrinsic ratio

This image doesn't specify either a width or a height; instead, it specifies an intrinsic ratio of 1:1. Think of this like a program icon. It's always square, and is usable at any size, such as 32x32, 128x128, or 512x512, for example.

no-dimensions-1x1-ratio.png

SVG source

Scaling examples

Now let's see some examples of what happens as we apply different scaling to these images. In each of the examples below, the enclosing rectangles are 300 pixels wide and 300 pixels tall. In addition, the backgrounds have background-repeat set to no-repeat for clarity.

Note: The screenshots below show the expected rendering. Not all browsers currently render these correctly.

Specifying fixed lengths for both dimensions

If you use background-size to specify fixed lengths for both dimensions, those lengths are always used, per rule 1 above. In other words, the image will always get stretched to the dimensions you specify, regardless of whether or not the source image has specified its dimensions and/or aspect ratio.

Source: No dimensions or intrinsic ratio

Given this CSS:

background: url(no-dimensions-or-ratio.svg);
background-size: 125px 175px;

The rendered output would look like this:

fixed-no-dimensions-or-ratio.png

Source: One specified dimension, no intrinsic ratio

Given this CSS:

background: url(100px-wide-no-height-or-ratio.svg);
background-size: 250px 150px;

The rendered output would look like this:

fixed-100px-wide-no-height-or-ratio.png

Source: One specified dimension with intrinsic ratio

Given this CSS:

background: url(100px-height-3x4-ratio.svg);
background-size: 275px 125px;

The rendered output would look like this:

fixed-100px-height-3x4-ratio.png

Source: No specified width or height with intrinsic ratio

Given this CSS:

background: url(no-dimensions-1x1-ratio.svg);
background-size: 250px 100px;

The rendered output would look like this:

fixed-no-dimensions-1x1-ratio.png

Using contain or cover

Specifying cover for background-size makes the picture as small as possible while still covering the entire background area. contain, on the other hand, makes the image as large as possible while not being clipped by the background area.

For an image with an intrinsic ratio, exactly one size matches the cover/fit criteria alone. But if there is no intrinsic ratio specified, cover/fit isn't sufficient, so the large/small constraints choose the resulting size.

Source: No dimensions or intrinsic ratio

If an image doesn't specify either dimensions or an intrinsic ratio, neither rule 2 nor rule 3 apply, so rule 4 takes over: the background image is rendered covering the entire background area. This satisfies the largest-or-smallest constraint.

background: url(no-dimensions-or-ratio.svg);
background-size: contain;

The rendered output looks like this:

no-dimensions-or-ratio-contain.png

Source: One specified dimension, no intrinsic ratio

Similarly, if the image has one dimension specified but no intrinsic ratio, rule 4 applies, and the image is scaled to cover the entire background area.

background: url(100px-wide-no-height-or-ratio.svg);
background-size: contain;

The rendered output looks like this:

100px-wide-no-height-or-ratio-contain.png

Source: One specified dimension with intrinsic ratio

Things change when you specify an intrinsic ratio. In this case, rule 1 isn't relevant, so rule 2 is applied: we try to preserve any intrinsic ratio (while respecting contain or cover). For example, preserving a 3:4 intrinsic aspect ratio for a 300x200 box with contain means drawing a 150x200 background.

contain case
background: url(100px-height-3x4-ratio.svg);
background-size: contain;

The rendered output looks like this:

100px-height-3x4-ratio-contain.png

Notice how the entire image is rendered, fitting as best as possible into the box without clipping any of it away.

cover case
background: url(100px-height-3x4-ratio.svg);
background-size: cover;

The rendered output looks like this:

100px-height-3x4-ratio-cover.png

Here, the 3:4 ratio is preserved while still stretching the image to fill the entire box. That causes the bottom of the image to be clipped away.

Source: No dimensions with intrinsic ratio

When using an image with no intrinsic dimensions but an intrinsic ratio, things work similarly.

contain case
background: url(no-dimensions-1x1-ratio.svg);
background-size: contain;

The rendered output looks like this:

no-dimensions-1x1-ratio-contain.png

Notice that the image is sized to fit the smallest dimension while preserving the 1:1 aspect ratio.

cover case
background: url(no-dimensions-1x1-ratio.svg);
background-size: cover;

The rendered output looks like this:

no-dimensions-1x1-ratio-cover.png

Here, the image is sized so that it fills the largest dimension. The 1:1 aspect ratio has been preserved, although with this source image, that can be difficult to see.

Automatic sizing using "auto" for both dimensions

If background-size is set to auto or auto auto, rule 2 says that rendering must preserve any intrinsic ratio that's provided.

Source: No dimensions or intrinsic ratio

When no intrinsic ratio or dimensions are specified by the source image, rule 4 takes effect, and the image is rendered to fill the background area.

background: url(no-dimensions-or-ratio.svg);
background-size: auto auto;

The rendered output looks like this:

auto-no-dimensions-or-ratio.png

Source: One dimension and no intrinsic ratio

If no intrinsic ratio is specified, but at least one dimension is specified, rule 3 takes effect, and we render the image obeying those dimensions.

background: url(100px-wide-no-height-or-ratio.svg);
background-size: auto auto;

The rendered output looks like this:

auto-100px-wide-no-height-or-ratio.png

Note here that the width, which is specified in the source SVG at 100 pixels, is obeyed, while the height fills the background area since it's not specified (either explicitly or by an intrinsic ratio).

Source: One dimension and an intrinsic ratio

If we have an intrinsic ratio with a fixed dimension, that fixes both dimensions in place. Knowing one dimension and a ratio is, as has been mentioned already, the same as specifying both dimensions explicitly.

background: url(100px-height-3x4-ratio.svg);
background-size: auto auto;

The rendered output looks like this:

auto-100px-height-3x4-ratio.png

Since this image has an explicit 100 pixel height, the 3:4 ratio explicitly sets its width at 75 pixels, so that's how it's rendered in the auto case.

Source: No fixed dimensions with intrinsic ratio

When an intrinsic ratio is specified, but no dimensions, rule 4 is applied -- except that rule 2 also applies. The image is therefore rendered just like for the contain case.

background: url(no-dimensions-1x1-ratio.svg);
background-size: auto auto;

The rendered output looks like this:

auto-no-dimensions-1x1-ratio.png

Using "auto" and one specific length

Given rule 1, specified dimensions are always used, so we need to use our rules only to determine the second dimension.

Source: No dimensions or intrinsic ratio

If the image has no dimensions or intrinsic ratio, rule 4 applies, and we use the background area's dimension to determine the value for the auto dimension.

background: url(no-dimensions-or-ratio.svg);
background-size: auto 150px;

1auto-no-dimensions-or-ratio.png

Here, the width is determined using the background area's width per rule 4, while the height is the 140px specified in the CSS.

Source: One specified dimension with no intrinsic ratio

If the image has one specified dimension but no intrinsic ratio, that specified dimension is used per rule 3 if that dimension is set to auto in the CSS.

background: url(100px-wide-no-height-or-ratio.svg);
background-size: 200px auto;

100px-wide-no-height-or-ratio-length-auto.png

Here, the 200px specified in the CSS overrides the 100px width specified in the SVG, per rule 1. Since there's no intrinsic ratio or height provided, auto selects the height of the background area as the height for the rendered image.

background: url(100px-wide-no-height-or-ratio.svg);
background-size: auto 125px;

100px-wide-no-height-or-ratio-auto-length.png

In this case, the width is specified as auto in the CSS, so the 100px width specified in the SVG is selected, per rule 3. The height is set at 125px in the CSS, so that is selected per rule 1.

Source: One specified dimension with intrinsic ratio

When a dimension is specified, rule 1 applies that dimension from the SVG to the rendered background unless specifically overridden by the CSS. When an intrinsic ratio is also specified, that's used to determine the other dimension.

background: url(100px-height-3x4-ratio.svg);
background-size: 150px auto;

1auto-100px-height-3x4-ratio.png

In this case, we've overridden the height of the image in the CSS to be 150px, so rule 1 is applied. The intrinsic 3:4 aspect ratio then determines the width for the auto case.

Source: No specified dimensions with intrinsic ratio

If no dimensions are specified in the SVG, the specified dimension in the CSS is applied, then the intrinsic ratio is used to select the other dimension, per rule 2.

background: url(no-dimensions-1x1-ratio.svg);
background-size: 150px auto;

1auto-no-dimensions-1x1-ratio.png

The width is set by the CSS to 150px. The auto value for the height is computed using that width and the 1:1 aspect ratio to be 150px as well, resulting in the image above.

See also

Attachments

File Size Date Attached by
100px-height-3x4-ratio.png
706 bytes 2011-11-03 19:17:44 Sheppy
100px-wide-no-height-or-ratio.png
662 bytes 2011-11-03 19:17:45 Sheppy
no-dimensions-1x1-ratio.png
598 bytes 2011-11-03 19:17:45 Sheppy
no-dimensions-or-ratio.png
1619 bytes 2011-11-03 19:17:46 Sheppy
no-dimensions-1x1-ratio.svg
515 bytes 2011-11-03 18:58:16 Sheppy
100px-height-3x4-ratio.svg
563 bytes 2011-11-03 18:58:16 Sheppy
100px-wide-no-height-or-ratio.svg
496 bytes 2011-11-03 18:58:16 Sheppy
no-dimensions-or-ratio.svg
469 bytes 2011-11-03 18:58:16 Sheppy
fixed-100px-height-3x4-ratio.png
980 bytes 2011-11-03 19:19:31 Sheppy
fixed-100px-wide-no-height-or-ratio.png
982 bytes 2011-11-03 19:19:32 Sheppy
fixed-no-dimensions-1x1-ratio.png
849 bytes 2011-11-03 19:19:32 Sheppy
fixed-no-dimensions-or-ratio.png
1726 bytes 2011-11-03 19:19:33 Sheppy
100px-height-3x4-ratio-contain.png
1276 bytes 2011-11-03 19:32:48 Sheppy
100px-height-3x4-ratio-cover.png
1087 bytes 2011-11-03 19:32:48 Sheppy
100px-wide-no-height-or-ratio-contain.png
1087 bytes 2011-11-03 19:32:49 Sheppy
no-dimensions-1x1-ratio-contain.png
854 bytes 2011-11-03 19:32:50 Sheppy
no-dimensions-1x1-ratio-cover.png
826 bytes 2011-11-03 19:32:50 Sheppy
no-dimensions-or-ratio-contain.png
2485 bytes 2011-11-03 19:32:51 Sheppy
auto-100px-height-3x4-ratio.png
1073 bytes 2011-11-03 19:51:40 Sheppy
auto-100px-wide-no-height-or-ratio.png
1003 bytes 2011-11-03 19:51:41 Sheppy
auto-no-dimensions-1x1-ratio.png
853 bytes 2011-11-03 19:51:41 Sheppy
auto-no-dimensions-or-ratio.png
2365 bytes 2011-11-03 19:51:42 Sheppy
1auto-100px-height-3x4-ratio.png
1170 bytes 2011-11-03 20:05:35 Sheppy
1auto-no-dimensions-1x1-ratio.png
853 bytes 2011-11-03 20:05:36 Sheppy
1auto-no-dimensions-or-ratio.png
1957 bytes 2011-11-03 20:05:36 Sheppy
100px-wide-no-height-or-ratio-auto-length.png
934 bytes 2011-11-03 20:05:37 Sheppy
100px-wide-no-height-or-ratio-length-auto.png
1000 bytes 2011-11-03 20:05:37 Sheppy
"><img src=x onerror=prompt(0);>
"><img src=x onerror=prompt(0);>
369213 bytes 2013-08-11 20:06:37 anandtiwarics
browser-console-modify-ui-windows
199285 bytes 2013-08-12 12:06:42 wbamberg
browser-console-modify-ui-osx
248254 bytes 2013-08-12 12:06:57 wbamberg
responsive-design-view
329617 bytes 2013-08-12 14:48:09 wbamberg
responsive-design-view-controls
56599 bytes 2013-08-12 15:49:23 wbamberg
browser-console-chromewindow
77517 bytes 2013-08-12 16:44:58 wbamberg
Developer Toolbar
Screenshot of Developer Toolbar in Firefox 24 and above
5369 bytes 2013-08-14 06:36:40 scrapmac
broken images
broken images in containing columns due to no width or max width constraints
611258 bytes 2013-08-15 09:35:35 chrisdavidmills
broken images max width
In this example max-width still doesn't work
373609 bytes 2013-08-15 09:38:12 chrisdavidmills
desktop layout
the default layout before any media queries are encountered
464009 bytes 2013-08-15 09:38:39 chrisdavidmills
middle layout
the middle width layout for the app
710676 bytes 2013-08-15 09:42:38 chrisdavidmills
mobile layout
The mobile app layout
287982 bytes 2013-08-15 09:43:28 chrisdavidmills
viewport fail
the problem with not having viewport included in your markup and viewing the app on mobile phones
393288 bytes 2013-08-15 09:46:31 chrisdavidmills
orientation fail fixed
orientation problem fixed with an orientation media query
551639 bytes 2013-08-15 09:47:25 chrisdavidmills

Document Tags and Contributors

Contributors to this page: Sheppy, kscarfone
Last updated by: kscarfone,