Skip to content

Optimization

SVG Optimization — A Complete Guide for Web Performance

A practical SVG optimization guide: SVGO, path simplification, viewBox handling, CSS vs inline, and the mistakes that bloat SVGs to 10× their real size.

SVG is the most misunderstood format on the web. Done right, a 10 KB logo becomes 2 KB, scales to any resolution, and renders crisp on any display. Done wrong, that same logo is 50 KB of editor metadata, unused definitions, and inline styles no one asked for. The gap between “bad SVG” and “good SVG” is bigger than the gap between “JPG” and “WebP.”

This guide covers what actually bloats SVGs, how to fix it, and when SVG isn’t the right answer at all.

Why raw SVG exports are huge

Open any SVG exported straight from Illustrator, Figma, Sketch, or Inkscape in a text editor. You’ll see something like this at the top:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 28.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<style type="text/css">
    .st0{fill:#FF6B35;}
    .st1{fill:none;stroke:#1A1A1A;stroke-width:2;stroke-miterlimit:10;}
</style>

Everything above the first <path> can usually be replaced with a single line. The id, the editor comment, the enable-background style, the xml:space, the generator-specific class names — all of it is dead weight. A typical editor export is 40-60% overhead. The actual shape data is the minority of the file.

On top of that, editors love to:

  • Emit hidden layers and slice frames that never render.
  • Embed base64-encoded raster fallbacks inside the SVG.
  • Leave paths at 6+ decimal places of precision.
  • Generate overlapping, redundant shapes that should have been boolean-combined.
  • Include <defs> and <clipPath> elements that were used during design but aren’t referenced in the final output.

What SVGO actually does

SVGO is the standard optimizer, and almost everything you want removed from an editor export is a one-command fix. A default SVGO pass typically:

  • Strips XML comments and doctype declarations.
  • Removes editor-specific namespaces and metadata.
  • Collapses useless groups (<g> with no attributes).
  • Rounds numeric precision to 3 decimal places (plenty for display).
  • Merges identical paths and styles.
  • Converts inline styles to attributes where shorter.
  • Removes unused <defs>.
  • Minifies path data (M10,10L20,20 becomes M10 10l10 10).

A 60 KB logo often drops to 6-8 KB after SVGO. Run SVGO on every SVG before shipping. It has no visible quality cost and no runtime cost.

The viewBox rule

The single most common SVG mistake is hardcoded width and height without a viewBox. A well-formed SVG looks like this:

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

Not like this:

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

Why? viewBox makes the SVG scalable — CSS can size it to whatever the container needs. Hardcoded width/height lock it to a specific size and defeat the main reason to use SVG at all. If you do want a default size, use CSS (.icon { width: 24px; }) and keep the viewBox intact.

Precision and path complexity

A path coordinate like M127.34561283 94.18273645 has 8 decimal places. At screen resolution, anything beyond 2 decimals is invisible. SVGO’s default of 3 decimals is a safe floor. Going to 1 decimal breaks visible quality on small curves but can cut file size 30% for path-heavy SVGs (complex illustrations, hand-drawn maps).

Path simplification goes deeper than rounding. If you traced a logo from a raster source, the tracer probably emitted 400 nodes on a curve that a human would draw with 12. Run a simplification pass — most editors have one under “Simplify Path” or equivalent — and accept a small quality hit for a large file size win.

SVG vs PNG vs WebP, by use case

SVG isn’t universally better. A rough decision matrix:

ContentBest formatWhy
Logo, icon, flat UI artSVGScales, small, sharp at any DPI
Complex illustration with many gradientsSVG or PNGSVG if <50 KB, PNG if bigger
Photographic imageWebP/AVIFSVG can’t compress photos well
Chart / graph with textSVGText stays selectable and sharp
Thumbnail at a single sizePNG or WebPSVG overhead not worth it
AnimationSVG (SMIL/CSS) or videoDepends on complexity

A common trap: vectorizing a photograph. Image to SVG tools can do this, but the result is often 10× the size of a well-compressed raster and doesn’t look as good. SVG is for graphics, not for photos. If you have a photo and want it to scale, ship a high-res WebP, not a traced SVG.

There’s a narrow case where photo vectorization makes sense: converting a PNG to SVG or a WebP to SVG for a stylized poster, sticker, or silkscreen output where the blocky flat-color look is the design goal. For those, SVG wins.

Inline SVG vs external file

Two ways to ship an SVG:

  1. External file referenced with <img>: cached separately, can be lazy-loaded, can’t be styled with CSS from the parent page.
  2. Inline in the HTML: styled freely with CSS, no extra HTTP request, but the markup ships on every page load and can’t be cached.

Rule of thumb: icons that appear on every page (site logo, UI icons) inline; decorative one-off images external. For a repeated icon set, use an SVG sprite — one external file with <symbol> blocks referenced by <use> elements. That gets you cache-ability plus styling.

Accessibility and SEO

An SVG without a <title> is invisible to screen readers. Add one inside the SVG:

<svg viewBox="0 0 24 24" role="img" aria-labelledby="title-menu">
  <title id="title-menu">Menu</title>
  <path d="..."/>
</svg>

For decorative SVGs, use aria-hidden="true" instead. Don’t leave assistive tech to guess what the graphic is.

A realistic optimization pipeline

For a site with a lot of SVG:

  1. Export from your design tool with “Minify” or “Optimized” mode if available.
  2. Run SVGO with a config that preserves viewBox and IDs referenced by JS.
  3. Remove or inline <style> blocks as appropriate for your rendering method.
  4. Build a sprite if you have more than ~10 reused icons.
  5. Gzip or Brotli at the server level — SVG is text, so it compresses another 60-80% on the wire.

File size targets:

  • UI icon: <1 KB optimized, <300 bytes gzipped.
  • Logo: <3 KB optimized, <1 KB gzipped.
  • Illustration: <20 KB optimized, <5 KB gzipped.

If you’re above those numbers after SVGO, the image is probably too complex for SVG — export as PNG or WebP and move on. SVG is a precision tool, not a universal format.

Related tools

Frequently asked questions

Does SVGO break animations or interactive SVGs?

By default SVGO preserves most things that matter, but it can strip IDs and attributes that your JS or CSS depends on. Before running it on an SVG with SMIL animation, CSS keyframes, or script hooks, configure SVGO to preserve IDs and the attributes you reference. For static icons and logos the defaults are safe; for animated or scriptable SVGs, audit the output once and lock in a config that keeps the hooks you need.

When should I inline SVG versus link it as an external file?

Inline SVGs that appear on every page (site logo, UI icons you need to style with CSS) because you save an HTTP request and gain full styling control. Use external files referenced with img for decorative or one-off images — they cache separately and can be lazy-loaded. For a set of more than about ten reused icons, build an SVG sprite: one external file with symbol blocks referenced by use, which gives you both caching and styling.

How much does gzip or Brotli compress SVG?

A lot — typically another 60-80% on the wire, because SVG is text and repeats many of the same tokens. That means a 10 KB optimized SVG lands around 2-3 KB compressed. Realistic targets after SVGO and gzip: UI icons under 300 bytes, logos under 1 KB, illustrations under 5 KB. If you're far above those numbers, the image is probably too complex for SVG and should be exported as PNG or WebP instead.

Why are SVGs exported from Figma or Illustrator so large?

Editor exports carry 40-60% overhead that has nothing to do with the shape data: editor comments, generator metadata, hidden layers, base64 raster fallbacks, unused defs and clipPaths, paths with 6+ decimal places of precision, and redundant overlapping shapes. Running SVGO strips most of this in one pass, typically shrinking a 60 KB editor export to 6-8 KB with no visible quality cost. Always run SVGO before shipping.

Should I keep width and height on my SVG or use viewBox only?

Always include viewBox. That's what lets the SVG scale to whatever size the container needs. Hardcoded width and height without viewBox lock the SVG to a specific size and defeat the main reason to use SVG in the first place. If you want a default display size, set it with CSS (.icon { width: 24px; }) and keep viewBox intact — CSS still respects the viewBox aspect ratio.

Sponsored