Blog · SVG foundations

The SVG viewBox is a coordinate map, not a canvas size.

A reliable mental model for viewport dimensions, user units, aspect-ratio fitting, nested transforms, and responsive SVG sizing.

Start by separating the viewport from user space.

The viewport is the rectangular region in which an SVG is displayed. In a web page its size may come from width and height attributes, CSS layout, an image element, or the dimensions of a containing component. User space is the coordinate system used by shapes inside that region. In the initial SVG coordinate system, the origin is normally at the top left, x increases to the right, and y increases downward.

These two rectangles do not have to use the same numbers. An SVG can occupy 640 by 360 CSS pixels while its drawing is described in a user space from 0 to 1600 horizontally and 0 to 900 vertically. Rendering maps one coordinate system into the other; the geometry does not need to be rewritten when the displayed size changes.

  • Viewport: the displayed rectangle
  • User space: the coordinates used by geometry
  • Mapping: the transform between those two spaces

Read viewBox as four numbers with distinct jobs.

A viewBox contains min-x, min-y, width, and height. The first pair selects the user-space origin visible through the viewport; the second pair defines the size of the visible user-space rectangle. A viewBox of 100 50 400 200 therefore exposes x coordinates from 100 to 500 and y coordinates from 50 to 250.

Changing min-x or min-y pans the visible region without moving individual shapes. Changing the viewBox width or height changes the scale needed to fit that region into the viewport. Width and height must be positive: a zero value disables rendering and a negative value makes the attribute invalid.

preserveAspectRatio decides how mismatched rectangles fit.

The default behaviour is xMidYMid meet. Scaling remains uniform, the complete viewBox stays visible, and any unused space is split around the centred drawing. This behaves like fitting a whole image inside a frame. The xMin, xMid, and xMax choices control horizontal alignment; YMin, YMid, and YMax do the same vertically.

The slice option also preserves proportions but fills the complete viewport, so part of the viewBox can fall outside the visible area. The none option permits different horizontal and vertical scale factors and therefore can distort circles, strokes, and letterforms. It is appropriate only when non-uniform stretching is intentional.

  • meet: show the whole viewBox and allow empty space
  • slice: fill the viewport and allow cropping
  • none: fill both dimensions and allow distortion

Transforms create local coordinate systems.

Every transform changes the coordinate system seen by an element and its descendants. A translated group can keep simple local coordinates even though it appears elsewhere in the document. Transform order matters because matrix multiplication is not commutative: translating and then rotating generally produces a different result from rotating and then translating.

Nested svg elements establish new viewports and can introduce another viewBox mapping inside the parent user space. Symbols, markers, patterns, gradients, clip paths, and masks may also use coordinate systems tied either to user space or to an object bounding box. When a reusable asset appears shifted or scaled unexpectedly, identify which coordinate system each referenced resource uses before changing its numbers.

Responsive size does not mean every visual feature scales identically.

A viewBox supplies an intrinsic aspect ratio, while CSS can choose the final displayed width. A common responsive arrangement gives the SVG a fluid width and lets its height follow the aspect ratio. Removing fixed dimensions without retaining a viewBox discards the coordinate map and can also make intrinsic sizing ambiguous.

Normal strokes scale with the current transformation. The non-scaling-stroke vector effect can keep stroke width visually constant while the geometry changes size, but markers, filters, dash patterns, and hit areas still deserve inspection. Percentages also resolve against properties defined by the current viewport or bounding box, so they are not interchangeable with user-unit numbers.

Debug the mapping before editing the geometry.

When an SVG looks cropped, stretched, or offset, first write down the viewport size, the four viewBox numbers, and the preserveAspectRatio value. Then inspect transforms from the outer svg element toward the affected shape. This order prevents compensating for a coordinate-system problem by permanently moving path points.

A useful diagnostic is to add a temporary rectangle matching the viewBox boundaries and a marker at its origin. If the rectangle fits but the artwork does not, the problem is inside the drawing or its transforms. If the rectangle itself fits incorrectly, the viewport mapping is the place to fix.

  • Verify viewport dimensions and CSS constraints
  • Verify viewBox origin and positive dimensions
  • Verify preserveAspectRatio before path coordinates
  • Inspect nested transforms from parent to child