Most exported SVGs carry 40–60% dead weight. Stripping it is easy. The trap is the handful of optimizations that also quietly break scaling, animation, or accessibility.
An SVG that a designer exports from Illustrator, Figma, or Inkscape is almost never the SVG you want to ship. A 16×16 icon that renders as a few hundred bytes of hand-tuned markup routinely comes out of an editor at two to four kilobytes: editor metadata, namespace declarations you'll never use, path coordinates carried to fifteen decimal places, and generated IDs that reference nothing. None of it is visible. All of it is downloaded, parsed, and — for inline icons — re-parsed on every page that embeds it.
Cleaning that up is one of the highest-return, lowest-effort optimizations in front-end work. But "optimize the SVG" hides a real cliff. Most transforms are perfectly safe and shave off dead weight. A small number of aggressive ones will make the icon scale wrong, kill a CSS hover animation, or strip the accessibility that a screen reader depends on. Knowing which is which is the entire skill.
What actually bloats an SVG
Before touching anything, it helps to know where the bytes go. In a typical editor export, the fat lives in a predictable set of places:
- Editor metadata.
<metadata>blocks,<sodipodi:*>and<inkscape:*>namespaced elements, Adobe<i:pgf>data, and XML comments describing the export. Pure overhead in a shipped file. - Excessive path precision. A coordinate like
d="M12.000000001,7.9999998 C..."carries far more decimals than any pixel grid can resolve. This is frequently the single largest source of bytes in an icon. - Unused defs and IDs. Gradients, filters, and
<clipPath>definitions left in<defs>that nothing references, plus auto-generatedidattributes on every node. - Inline presentation cruft. Redundant attributes (
fill="#000000"when black is already the default in context), empty groups, and default transforms liketransform="translate(0,0)". - Verbose numeric and color forms.
#ffffffinstead of#fff,0.5instead of.5, absolute path commands where relative ones encode shorter.
Removing all of the above changes nothing about how the icon looks. This is the safe zone, and it typically accounts for the bulk of the savings.
Safe optimizations
These can be applied to essentially any SVG without visual or functional risk:
- Strip metadata, comments, and editor namespaces. Nothing at render time reads them.
- Collapse whitespace and remove indentation. XML doesn't care; the parser doesn't either.
- Remove unused
defsand dead IDs. With the important caveat below about IDs that are targeted externally. - Shorten colors and numbers. Hex shortening, dropping leading and trailing zeros, and converting to relative path commands are all lossless.
- Round path precision to a sane number of decimals. Lossy in principle, invisible in practice when done correctly — see below.
The decimal-precision floor
Precision reduction is where most of the byte savings hide, and it's also where people get nervous. The question is: how many decimals does a path coordinate actually need?
The answer depends on the viewBox, because path coordinates are expressed in user units, and the ratio of user units to rendered pixels is set by the viewBox and the display size. For a typical icon with a viewBox like 0 0 24 24 rendered anywhere from 16px to 64px, two decimal places is almost always indistinguishable from the original, and one decimal place is often fine. Two decimals on a 24-unit grid resolves to 1/100th of a user unit — finer than a single device pixel at any normal icon size.
The rule of thumb: the larger the viewBox coordinate space relative to display size, the more decimals matter. A detailed illustration authored on a 0 0 2000 2000 canvas and shown at 500px can lose visible sharpness if you round too hard, so keep three decimals there. A small UI icon can usually go to one or two. When in doubt, round to two, render at the largest size you actually use, and compare. The savings from 15 decimals down to 2 are dramatic; the savings from 2 down to 1 are marginal and not worth a visual risk.
Risky optimizations
These are the ones that ship in aggressive presets and cause the "it worked, then it broke" bug reports. Each is legitimate in the right circumstances and destructive in the wrong ones.
- Removing the
viewBox. This is the classic footgun. The viewBox defines the coordinate system and is what makes an SVG scale responsively. Strip it and the SVG falls back to its intrinsicwidth/heightand stops scaling to its container — the icon renders at a fixed size or collapses. Never remove the viewBox on anything meant to scale. Most SVGs are meant to scale. - Flattening transforms. Baking
transformattributes into the path data (recomputing coordinates so the transform can be deleted) reduces size and is usually safe — but if CSS or JavaScript animates that transform, flattening removes the very thing being animated, and the motion disappears. - Merging and collapsing paths. Combining multiple
<path>elements into one is smaller, but only correct when they share fill, stroke, and opacity. Merge across differing styles and you change the render. Merge paths that were separately targeted by CSS (say, a two-tone icon) and you lose the ability to color them independently. - Stripping IDs and classes. Safe for internal-only IDs, dangerous when an
idorclassis a hook for external CSS, a<use>reference, a JavaScript selector, or a gradient/filter reference. Removing the ID that afill="url(#grad)"points at breaks the fill entirely. - Removing
title,desc, and ARIA attributes. These are accessibility, not decoration. An icon-only button whose meaning comes from<title>oraria-labelbecomes invisible to a screen reader if an optimizer strips them as "unused text."
Optimization, saving, and risk at a glance
| Optimization | Typical saving | Risk |
|---|---|---|
| Strip metadata / comments | 10–30% | None |
| Precision → 2 decimals | 20–50% | Low (verify at max size) |
| Shorten colors / numbers | 3–8% | None |
| Remove unused defs/IDs | 5–20% | Medium (external refs) |
| Flatten transforms | 2–10% | Medium (breaks animation) |
| Merge paths | 3–15% | Medium (styling / color) |
| Remove viewBox | <1% | High (breaks scaling) |
The pattern is clear: the biggest savings come from the safest operations, and the riskiest operation (dropping the viewBox) saves almost nothing. That asymmetry is the whole argument for a conservative preset.
Gzip and brotli change the math
SVG is text, and text compresses extremely well. Any competent server serves it with gzip or brotli, and that transport compression sits on top of your minification. This matters because the two overlap: much of what minification removes (whitespace, repeated attribute names, verbose numbers) is exactly what gzip would have compressed away for free.
The practical consequence: measure the size after compression, not before. A minification step that halves the raw file might only shave 10–15% off the gzipped size, because the compressor was already handling the redundancy. Precision reduction is the exception — it removes actual entropy (real, distinct digits), so it shrinks the compressed size too. So when you're optimizing for over-the-wire bytes, precision reduction and structural removal (unused defs, metadata) pay off after gzip; cosmetic minification largely does not. Always confirm both the server is compressing and that the win survives compression before treating a transform as worthwhile.
Tool walkthrough
Toolhub's SVG optimizer runs entirely in the browser — the file never leaves the machine — and defaults to the safe preset: it strips metadata, comments, and editor namespaces, shortens colors and numbers, and rounds path precision to a sensible default while keeping the viewBox, title/desc, and ARIA attributes intact. The riskier operations (flattening transforms, merging paths, aggressive ID removal) are opt-in toggles, so you can enable them deliberately and eyeball the preview rather than discovering later that a hover animation vanished. It reports both raw and estimated gzipped size, which is the number that actually reaches your users.
For raster assets that don't belong in vector form in the first place — a photo someone dropped into an "SVG" as an embedded base64 bitmap, for instance — the right move isn't SVG optimization at all. Route those through image compress to get a properly encoded PNG, JPEG, or WebP, then reference it as a normal image rather than inflating a vector file with binary payload.
Where to read further
- W3C SVG 2 specification — the authoritative definition of the coordinate system, the viewBox, transforms, and the
title/descaccessibility elements. - MDN: SVG documentation — practical references for elements, attributes, the viewBox and preserveAspectRatio, and scripting/animation hooks that optimization can break.
- SVGO project — the widely used open-source optimizer whose plugin list is a good catalogue of every transform, safe and risky, described in this article.
SVG optimization is mostly free money: strip the editor exhaust, round the coordinates, shorten the numbers, and a bloated export drops to a fraction of its size with zero visual change. The discipline is in knowing where to stop — leave the viewBox, keep the accessibility, and treat transform-flattening and path-merging as deliberate choices you verify, not defaults you trust. Optimize to the floor, not past it.
← All articles