To remove unexpected space around an SVG use instance, identify whether it comes from the source viewBox, aspect-ratio fitting, or the surrounding CSS line box. This guide shows how to diagnose and fix each cause while keeping placement coordinates predictable.
The task is a small desktop webpage edit: position a reusable shape precisely inside an SVG, then make its surrounding HTML layout fit as intended. You can follow the examples in a plain-text editor on your Mac and open the saved HTML file in a current desktop browser.
Which coordinate system controls the space?
There are three boundaries to inspect: the outer SVG element’s CSS box, the viewport used for a referenced symbol, and the actual shape inside that symbol. W3C explicitly distinguishes an SVG viewport from the browser’s CSS viewport. A viewBox maps SVG user coordinates into an SVG viewport; it does not describe the browser window. Coordinate Systems, Transformations and Units — SVG 2
For example, x="20" on a use element supplies an offset in its SVG coordinate system. It does not mean 20 CSS pixels from the browser window’s left edge. Scaling and ancestor transforms can change where that offset appears on the page. The SVG specification describes use positioning as an additional translation, with behavior distinct from CSS box layout. Document Structure — SVG 2
Start with this decision table. It is a diagnostic sequence derived from the documented layout mechanisms, rather than a list of interchangeable fixes.
| What you observe | What to inspect first | Likely correction |
|---|---|---|
| A narrow strip below the entire SVG | Inline formatting and the parent’s line height | Make a standalone SVG block-level, or adjust its inline alignment |
| Empty space inside each repeated graphic | Shape coordinates versus the symbol’s viewBox |
Tighten the source bounds if the inset is unintended |
| Extra space on two sides of a symbol instance | Instance dimensions versus the viewBox ratio |
Match the ratios or choose a deliberate fitting policy |
| Correct local placement but wrong page position | SVG user units versus browser viewport coordinates | Convert coordinates before assigning x and y |
| Changing instance dimensions does nothing | The element targeted by href |
Use a viewport-defining symbol for fitting, or transform the geometry |
Reproduce the gap with a complete local example
Save the following complete document as svg-spacing.html in a plain-text editor, then open it in your browser. It uses only synthetic labels and rectangles, with no libraries or external files. The pale rectangles mark the intended instance viewports; the darker rectangles are the reused artwork.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>SVG spacing example</title>
<style>
body {
margin: 24px;
font: 16px system-ui, sans-serif;
}
#canvas {
display: block;
width: 320px;
height: 200px;
outline: 1px solid #687580;
background: #fff;
}
.viewport-guide { fill: #e4edf2; }
.artwork { fill: #356b8c; }
text { fill: #253744; font-size: 14px; }
</style>
</head>
<body>
<p>Two instances with different source bounds and fitting dimensions.</p>
<svg id="canvas" xmlns="http://www.w3.org/2000/svg"
width="320" height="200" viewBox="0 0 320 200"
role="img" aria-labelledby="drawing-title">
<title id="drawing-title">Padded and tightly fitted rectangles</title>
<defs>
<symbol id="padded" viewBox="0 0 100 100">
<rect id="source-shape" class="artwork"
x="20" y="20" width="60" height="60" />
</symbol>
<symbol id="tight" viewBox="20 20 60 60">
<rect class="artwork"
x="20" y="20" width="60" height="60" />
</symbol>
</defs>
<rect class="viewport-guide"
x="20" y="20" width="120" height="60" />
<use href="#padded" x="20" y="20" width="120" height="60" />
<text x="160" y="55">Padded source</text>
<rect class="viewport-guide"
x="20" y="110" width="60" height="60" />
<use id="tight-instance" href="#tight"
x="20" y="110" width="60" height="60" />
<text x="110" y="145">Tight source</text>
</svg>
</body>
</html>
Both instances explicitly set their dimensions. This avoids relying on implicit sizing while investigating the gap. MDN documents use as reusing referenced SVG content and notes that its width and height affect fitting when the target is an SVG or symbol with a viewBox. The example uses the current href attribute. MDN: use
Calculate where the first rectangle actually starts
The first source has a 100-by-100 viewBox, but its rectangle occupies only coordinates 20 through 80 in each direction. Its requested instance viewport is 120 by 60. With the default xMidYMid meet fitting, the scale is the smaller of 120 / 100 and 60 / 100: 0.6. The scaled viewBox occupies 60 by 60, leaving 30 units on each horizontal side. This follows W3C’s viewport transformation algorithm. SVG 2: Computing the equivalent transform of an SVG viewport
For these illustrative inputs, the painted rectangle starts at 20 + 30 + 20 × 0.6 = 62 horizontally and 20 + 20 × 0.6 = 32 vertically. Its size is 60 × 0.6 = 36 in each direction. The arithmetic was checked with a small deterministic calculation; these are calculated values, not measurements from a browser test.
The second instance changes two independent inputs: its source bounds become 20 20 60 60, and its instance viewport becomes 60 by 60. The rectangle therefore fills that viewport and begins at SVG coordinate (20, 110). To isolate the causes yourself, change just one input at a time.
How do you remove space inside the instance?
Correct unintended space in the source bounds
A viewBox contains four numbers: minimum x, minimum y, width, and height. Its origin does not have to be zero. In the example, viewBox="20 20 60 60" describes the rectangle’s existing bounds without rewriting its geometry. MDN: viewBox
Before tightening a real graphic, decide whether its inset is intentional. A set of reusable shapes may share a common coordinate frame so that their visual sizes and positions remain consistent. Tightening each symbol independently can change those relationships. Keep shared bounds when that consistency is part of the design.
For geometry inspection, getBBox() reports bounds in SVG user coordinates. By default, it excludes strokes and markers, and it does not account for transforms applied to the target element or its parents. Consequently, a fill-only bounding box is not sufficient evidence for cropping stroked or transformed artwork. MDN: SVGGraphicsElement getBBox()
Choose how mismatched aspect ratios should fit
Even tightly bounded artwork can have surrounding space when a square source is fitted into a wide viewport. Choose the policy according to the desired result. Apply preserveAspectRatio to the referenced symbol for its internal fitting, or to the outer SVG when diagnosing the outer coordinate mapping. MDN: preserveAspectRatio
| Choice | Result and condition |
|---|---|
| Matching source and viewport ratios | Avoids aspect-ratio fitting space while retaining proportions |
xMidYMid meet |
Shows the entire viewBox, centered; mismatched ratios leave space |
xMinYMin meet |
Moves the fitted viewBox toward the top-left; remaining space still exists |
none |
Allows nonuniform scaling; a square can become a rectangle |
xMidYMid slice |
Covers the viewport, but some source content extends beyond it; clipping determines visibility |
Changing alignment moves fitting space; it does not remove an inset already encoded in the source geometry. Likewise, slice is unsuitable when all source content must remain inside the viewport. These distinctions follow MDN’s definitions of alignment, meet, slice, and nonuniform fitting. MDN: preserveAspectRatio
Check the reference target when dimensions appear ineffective
A plain group or path does not gain a fitting viewport merely because a use element references it. W3C states that instance width and height have no effect when the referenced element does not establish a new viewport. For predictable per-instance fitting, place the reusable geometry in a symbol with explicit bounds, as above. For direct geometric scaling, use a transform and account for its effect on placement. SVG 2: Layout of re-used graphics
How do you remove the strip below the outer SVG?
A gap outside the SVG can come from HTML inline formatting. WHATWG permits SVG in phrasing content; the surrounding page can therefore place it alongside text. CSS line boxes include font metrics above and below the baseline, so an inline graphic can leave visible space beneath its box. HTML Standard: SVG, CSS 2: Line height calculations
The complete example already sets display: block on #canvas, which removes that SVG from inline line-box participation. For a standalone drawing, keep that rule. To investigate the mechanism, temporarily change it to display: inline and inspect the surrounding line.
For an SVG that must remain beside text, try vertical-align: bottom on the outer SVG and check the resulting text alignment. This property aligns an inline-level box within its line; it does not change symbol bounds or internal fitting. Other content and the parent’s line height can still determine the line’s total height. MDN: vertical-align
Treat these CSS declarations as alternatives for the outer SVG, not cumulative fixes to paste onto each instance:
/* Standalone drawing */
#canvas {
display: block;
}
/* Alternative when the drawing must stay inline */
/*
#canvas {
display: inline;
vertical-align: bottom;
}
*/
What if your coordinates come from the browser viewport?
getBoundingClientRect() reports an element’s position relative to the browser viewport in CSS pixels. Its position changes as the page scrolls. Those values belong to a different space from SVG user coordinates, so copying its left and top directly into an instance’s x and y is generally incorrect. MDN: Element getBoundingClientRect()
Use a coordinate transformation when the input is a browser viewport point. getScreenCTM() supplies the SVG transformation matrix, and applying its inverse converts the point back into the chosen element’s local coordinates. A point’s matrixTransform() method performs the conversion. MDN: getScreenCTM(), MDN: matrixTransform()
The following console snippet is an optional extension to the complete document above. It converts the browser viewport point (100, 150) into the outer SVG’s user coordinates and moves the tightly bounded instance there. It assumes the example’s untransformed instance remains a direct child of that SVG.
(() => {
const canvas = document.getElementById("canvas");
const instance = document.getElementById("tight-instance");
if (!canvas || !instance) {
throw new Error("Open the complete SVG spacing example first.");
}
const matrix = canvas.getScreenCTM();
if (!matrix) {
throw new Error("The SVG coordinate matrix is unavailable.");
}
const viewportPoint = new DOMPoint(100, 150);
const localPoint = viewportPoint.matrixTransform(matrix.inverse());
if (!Number.isFinite(localPoint.x) || !Number.isFinite(localPoint.y)) {
throw new Error("The SVG coordinate matrix cannot be inverted.");
}
instance.setAttribute("x", String(localPoint.x));
instance.setAttribute("y", String(localPoint.y));
})();
The finite-number check matters because a noninvertible matrix produces NaN components. Recompute the matrix when converting a new point after layout or scrolling changes. If your instance is inside a transformed group, convert into that parent group’s coordinate system instead. This snippet was inspected against the API documentation; it was not executed in a browser during research. MDN: DOMMatrixReadOnly inverse()
Finish by checking the three boundaries separately: the outer SVG box, the symbol’s fitted viewport, and the artwork’s own bounds. Correct the boundary that introduces the unwanted space, then confirm the result at the intended page size. That gives you predictable placement without compensating for an unexplained gap with arbitrary offsets.
Sources
- Coordinate Systems, Transformations and Units — SVG 2 — W3C.
- Document Structure — SVG 2 — W3C.
use— MDN Web Docs.- viewBox — MDN Web Docs.
- preserveAspectRatio — MDN Web Docs.
- SVGGraphicsElement: getBBox() method — MDN Web Docs.
- HTML Standard — SVG — WHATWG.
- Visual formatting model details — W3C.
- vertical-align CSS property — MDN Web Docs.
- Element: getBoundingClientRect() method — MDN Web Docs.
- SVGGraphicsElement: getScreenCTM() method — MDN Web Docs.
- DOMPointReadOnly: matrixTransform() method — MDN Web Docs.
- DOMMatrixReadOnly: inverse() method — MDN Web Docs.