How to Optimize SVG Files with SVGO

This guide is the first step in SVG & Icon Optimization, within Image & Media Optimization. SVGs exported from design tools are written for editability, not delivery. They carry editor metadata, layer names as IDs, hidden layers, unused definitions, default attribute values spelled out in full, nested groups that do nothing, and path coordinates with far more decimal places than any screen can show. None of it changes what users see; all of it costs bytes in HTML (for inline SVG) or in requests (for files).

SVGO is the standard tool for removing that bloat. Its default preset applies dozens of safe transformations — removing metadata and comments, collapsing groups, merging paths, shortening colours and numbers. Typical savings are 30–80% for exported icons and illustrations. The main risks are a few transformations that can change appearance or break CSS and JavaScript that depend on IDs and classes, which a short configuration controls.

SVGO savings on typical exports Bar chart of file size before and after SVGO for an icon, a logo and an illustration exported from a design tool. SVGO savings on typical exports Icon before 4.8KB Icon after 0.9KB Logo before 22KB Logo after 6.1KB Illustration before 148KB Illustration after 61KB

Rapid Diagnosis

  • Open an exported SVG in a text editor. Look for <metadata>, sodipodi:, inkscape: or data-name attributes, <!-- Generator: ... --> comments, and coordinates like 12.000000.
  • Check sizes of SVG assets in the build output and of inline SVG in HTML.
  • Check whether SVGO already runs. Many build setups optimise imported SVG components but not SVGs in public/ or CMS uploads.
  • Look for embedded rasters. <image href="data:image/png;base64,…"> inside an SVG means a bitmap disguised as a vector.

Root Cause Analysis

1. Editor-oriented exports. Tools preserve layer structure, names and metadata to support round-tripping.

2. Excess precision. Coordinates with five or six decimals are common; two or three suffice at typical display sizes.

3. Redundant structure. Empty groups, transforms that could be applied to paths, and duplicated style attributes.

4. No automation. Files are optimised once by hand, then replaced by new unoptimised exports.

What SVGO removes or rewrites Categories of SVG bloat, what SVGO does with them, and whether the default is safe. What SVGO removes or rewrites Bloat SVGO action Safe by default? Editor metadata and comments remove yes Excess numeric precision round to N decimals check precision Empty groups / useless transforms collapse / apply yes IDs and classes remove or minify breaks CSS/JS refs viewBox removed by some presets keep it

Step-by-Step Resolution

1. Create a shared, safe configuration

javascript
// svgo.config.mjs
export default {
  multipass: true,
  floatPrecision: 2,
  plugins: [
    { name: 'preset-default', params: { overrides: {
      removeViewBox: false,          // keep responsive scaling
      cleanupIds: { minify: false }, // keep IDs referenced from CSS/JS
    } } },
    'removeDimensions',              // size via CSS + viewBox instead of fixed width/height
    { name: 'removeAttrs', params: { attrs: ['data-name'] } },
  ],
};
// trade-off: removeDimensions suits icons styled by CSS; for <img> SVGs that
// rely on intrinsic size, drop it and set width/height on the img element.

2. Run it over existing assets

bash
npx svgo --config svgo.config.mjs -rf src/assets/svg -o src/assets/svg
# trade-off: optimising in place is irreversible in the working tree; commit
# first so you can diff and review visual changes.

Expected outcome: smaller files with identical rendering for the vast majority of assets.

3. Integrate into the build

Use your bundler's SVG plugin with the same config so imported SVGs and copied assets are always optimised — for example vite-plugin-svgr or unplugin-icons with SVGO options, or svgo-loader/image-minimizer-webpack-plugin for webpack. For SVGs in public/ (copied verbatim), run SVGO as a pre-build step.

4. Guard against regressions in CI

Fail the build if an SVG asset is significantly larger than its optimised form, or simply run SVGO in check mode and compare sizes.

SVGO in the asset pipeline Pipeline from a designer export through SVGO in the build and a CI size check to the shipped asset. SVGO in the asset pipeline Export design tool Commit raw SVG Build SVGO shared config CI check size + visual diff Ship optimised asset

Verification

Compare file sizes before and after, and visually diff a sample of icons and illustrations (render both versions to PNG with a headless browser and compare pixels). Check that CSS and JavaScript referencing SVG IDs or classes still work. For inline SVG, HTML size per page should fall accordingly.

Worked Example: A Marketing Site's Illustrations

A marketing site used 34 decorative illustrations exported from a design tool, averaging 96KB each, several inlined in the homepage HTML. The homepage HTML was 410KB uncompressed. Running SVGO with multipass and two-decimal precision reduced illustrations to an average of 38KB; three that contained embedded PNG textures were re-exported as AVIF images instead. Homepage HTML fell to 190KB, and LCP on mobile improved by about 150ms because the HTML — which contained the LCP heading — arrived sooner.

Choosing Precision

floatPrecision is the setting with the biggest effect on size and the main source of visual changes. Icons drawn on a 24-unit grid need little precision: one or two decimals are invisible at icon sizes. Detailed illustrations scaled to full width may show tiny distortions at one decimal; two or three are safer. Test at the largest size each asset is displayed. A useful habit is to set precision per asset class in configuration (icons, logos, illustrations) rather than one global value.

Common Mistakes

  • Removing the viewBox. Breaks scaling when dimensions are removed or overridden.
  • Minifying IDs used by CSS or scripts. Animations and styles that target IDs stop working.
  • Optimising only once. Without build integration, new exports reintroduce bloat.
  • Ignoring embedded rasters. SVGO cannot shrink base64 PNGs inside SVG meaningfully; re-export as a raster image.

Edge Cases

Accessibility attributes. Keep <title>, role and aria-* attributes on meaningful SVGs; check that your preset does not strip them.

Animated SVG. SMIL animations and CSS animations referencing internal IDs or classes need those preserved.

Sprites. Optimise individual icons before building a sprite; some sprite tools run SVGO themselves.

Third-party SVGs. Logos and badges from partners are often unoptimised; optimise copies you host.

FAQ

Is SVGO safe to run on every SVG?

The default preset is safe for the overwhelming majority of files. The exceptions are files whose IDs or classes are referenced externally and files that rely on dimensions or viewBox behaviour — handled by the overrides above. Review diffs the first time you run it on an existing collection.

How much does SVGO save after gzip?

Less than the raw percentage suggests, because repetitive metadata compresses well — but still substantial, often 20–50% of compressed size, and the parse and DOM benefits apply to uncompressed size.

Should I use multipass?

Yes for build pipelines. It runs the plugins repeatedly until no further savings occur, which finds a few extra percent at the cost of slightly longer optimisation time.

Can SVGO convert shapes to paths?

Yes (convertShapeToPath, in the default preset), which often saves bytes. It can complicate later editing, which is why the source files should stay unoptimised in a design repository.

What about SVG in CSS data URIs?

Optimise them too, and URL-encode rather than base64-encode them for smaller output. For anything beyond tiny glyphs, prefer external files that cache separately from CSS.

Do image CDNs optimise SVG?

Some sanitize and minify SVGs; many pass them through unchanged. Do not rely on the CDN — optimise in the build where you control the configuration.

Should SVGO run on SVGs uploaded through a CMS?

Yes — user and editor uploads are often the least optimised assets on a site. Run SVGO (plus a sanitiser that removes scripts and event handlers, for security) on upload or in the image pipeline before files are published.

Does SVGO affect accessibility titles?

The default preset removes <title> in some versions (removeTitle). Disable that plugin for meaningful graphics, or provide accessible names on the referencing element instead.

How long does SVGO take in a build?

Milliseconds per file for icons and well under a second for large illustrations, so even hundreds of files add little build time. Cache results by content hash in CI if you have thousands of assets.