web3icons

Understanding the SVG viewBox

What the four numbers in an SVG viewBox mean, how they interact with width, height and preserveAspectRatio, and how to fix cropped or badly padded icons.

5 min read

When an icon refuses to scale, gets its edges cut off, or sits oddly small next to its neighbors, the cause is almost always the viewBox attribute. It is four numbers on the root <svg> element, and once you can read them you can fix most sizing bugs in a text editor without touching the artwork.

The four numbers

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">

The values are min-x min-y width height. Together they define a rectangle in the drawing's own coordinate system, called user units:

  • min-x and min-y: the coordinates of the rectangle's top-left corner.
  • width and height: how many user units the rectangle spans.

So 0 0 24 24 means "the visible area runs from (0, 0) to (24, 24)". Every coordinate in the file's paths and shapes is measured on this grid. A circle with cx="12" cy="12" r="10" sits in the center with 2 units of space on each side.

User units are not pixels. They only become pixels when the SVG is displayed at some size.

viewBox and width/height do different jobs

The width and height attributes (or CSS) set the viewport: the box on the page the SVG occupies. The viewBox says which part of the drawing to fit into that box. The browser scales one onto the other.

viewBox Displayed at Scale 1 user unit equals
0 0 24 24 24 × 24 px 1 1 px
0 0 24 24 48 × 48 px 2 2 px
0 0 24 24 16 × 16 px 0.667 0.667 px
0 0 2000 2000 32 × 32 px 0.016 0.016 px

This is why a well-formed icon can be dropped into any size and stay proportional. The coordinates never change; only the scale does.

It also explains the opposite. If the viewBox does not exist, there is nothing to scale from.

When the box and the drawing disagree

If the viewport has a different aspect ratio from the viewBox, preserveAspectRatio decides what happens. The default is xMidYMid meet, which you rarely need to write out.

Take an icon with viewBox="0 0 24 24" placed in a 48 × 24 px box:

preserveAspectRatio Result
xMidYMid meet (default) Scaled to fit entirely (24 × 24 px), centered, 12 px of empty space left and right
xMinYMid meet Same size, pushed to the left edge
xMidYMid slice Scaled to cover the box (48 × 48 px), top and bottom cropped by 12 px each
none Stretched to 48 × 24 px, so a round coin becomes an oval

For logos, keep the default. none distorts the mark, and slice crops it. slice is useful for background artwork that must fill a hero area, not for icons.

Common viewBox bugs

The icon does not scale

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
  <circle cx="12" cy="12" r="10" fill="#6b7280"/>
</svg>

Set this to 48 px with CSS and, inline in a page, you get a 48 px box with the original 24 px drawing stuck in its top-left corner. Without a viewBox, one user unit stays one pixel. The fix is to add a viewBox that matches the original width and height:

<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">

Behavior without a viewBox also varies between contexts (inline, <img>, CSS backgrounds), which makes the bug look intermittent. Adding the viewBox makes it predictable everywhere.

Edges are cut off

Anything outside the viewBox rectangle is not shown. A stroke that sits on the edge of the artboard is the usual victim: a circle with r="12" in a 0 0 24 24 box and a stroke-width="2" loses half its stroke, because SVG strokes are centered on the path and the outer half falls outside.

Fixes, in order of preference:

  1. Outline the stroke in your design tool and keep the shape inside the artboard.
  2. Shrink the shape (for example r="11").
  3. Widen the viewBox: -1 -1 26 26 adds one unit on every side.

To see what is being clipped while debugging an inline SVG, add style="overflow: visible" to the root element temporarily. That does not help an SVG loaded through <img>, which is always clipped to its box.

Padding is wrong or inconsistent

Some exports include generous padding; some crop tightly to the artwork. Put icons from both sources in the same list and the tightly cropped ones look bigger. You can adjust padding without editing a single path, because padding is just the viewBox being larger or smaller than the artwork:

  • Add 2 units of padding to a 24-unit icon: change 0 0 24 24 to -2 -2 28 28.
  • Remove 2 units: change 0 0 24 24 to 2 2 20 20.

The width and height of the viewBox stay equal, so the icon stays square, and min-x and min-y shift by the same amount so it stays centered. Deciding how much padding a set should have is a design decision; the icon set audit guide covers how to make it once and apply it everywhere.

Strange numbers from exports

A viewBox such as 312.5 -40 24 24 usually means the artwork was exported from a large canvas without being moved to the origin. It renders correctly, but it is confusing to edit. Re-export from a frame positioned at (0, 0), or leave it alone if nothing else is wrong.

Computing a tight, square viewBox

When you need to fix many files, measure the artwork rather than guessing. Open the SVG inline in a browser page and run this in the console:

const svg = document.querySelector('svg')
const box = svg.getBBox()

function squareViewBox({ x, y, width, height }, padding = 0) {
  const size = Math.max(width, height) + padding * 2
  const minX = x - (size - width) / 2
  const minY = y - (size - height) / 2
  return `${minX} ${minY} ${size} ${size}`
}

console.log(squareViewBox(box, 1))

getBBox() returns the bounding box of the shapes in user units. It ignores stroke width, so add at least half the stroke width to the padding for stroked artwork. The function centers the artwork in a square and adds the padding you ask for.

Round the result to two decimals before writing it back. A viewBox of -1.37 0.42 26.5 26.5 is fine; nobody needs ten decimal places.

A quick checklist

  • Every icon file has a viewBox.
  • Width and height of the viewBox are equal for square icons.
  • Nothing important sits outside the viewBox, including stroke halves.
  • Padding is consistent across the set.
  • preserveAspectRatio is either absent or left at its default for logos.

Once the viewBox is right, the display size is purely a CSS question. The guide on making SVGs scale responsively picks up from there, and editing an SVG by hand shows where the attribute sits in a real file.

More in SVG

All guides