Back to blog

Optimizing SVGs with SVGO Without Breaking Accessibility

svgsvgoperformanceaccessibility

SVG files exported from design tools are often much larger than they need to be. They carry editor metadata, comments, redundant attributes and overly precise numbers that make no visible difference. SVGO, a Node.js command-line optimizer, removes that excess automatically. But its aggressive defaults can also strip things you want to keep, including the accessible name of an image and the viewBox that lets it scale. This guide shows how to shrink files safely.

What SVGO removes

  • Editor metadata and namespaces, such as those added by Inkscape and other tools.
  • Comments, empty groups and unused definitions.
  • Unneeded precision in path coordinates.
  • Default attribute values that are redundant.
  • Optionally, the title and desc elements and the viewBox attribute, depending on configuration.

Cleaning a fresh export from a design tool can shrink it dramatically. Some guides report that a raw export can be around ten times larger than its optimized version, though results vary from file to file.

Running SVGO

You can run SVGO without installing it permanently. Point it at a single file or an entire folder, and it rewrites the files or writes to an output directory.

npx svgo icon.svg -o icon.min.svg
npx svgo -f ./icons -o ./icons-min

Keep the viewBox

The viewBox attribute defines the SVG's internal coordinate system. Without it, the image cannot scale to fit whatever size you give it in CSS, and your icon may be cropped or stay at a fixed size. Some SVGO setups remove it to save a few bytes, so check that yours does not. Guides on SVG optimization consistently recommend disabling the removal of viewBox so files scale responsively.

Keep title and desc for accessibility

The title element gives an SVG its accessible name, and desc can provide a longer description for complex graphics. An optimizer that strips them makes the image invisible to screen readers. If your icons carry meaning, configure SVGO to leave these elements alone. A frontend checklist describes a preset configuration that disables the removal of title and desc for exactly this reason.

An example configuration

Create an svgo.config.js file in your project. The structure below overrides the defaults to keep the viewBox and title. Plugin names and defaults change between SVGO versions, so confirm them in the documentation for the version you use.

// svgo.config.js
module.exports = {
  plugins: [
    {
      name: 'preset-default',
      params: {
        overrides: {
          removeViewBox: false,
          removeTitle: false,
        },
      },
    },
  ],
};

Marking up accessible SVGs

For an inline SVG that conveys information, give it role img and connect it to its title and description with aria-labelledby. For a decorative icon, hide it from assistive technology instead.

<svg role="img" aria-labelledby="t d" viewBox="0 0 24 24">
  <title id="t">Download</title>
  <desc id="d">An arrow pointing down into a tray</desc>
  <path d="..." />
</svg>

<!-- decorative -->
<svg aria-hidden="true" viewBox="0 0 24 24">...</svg>

Check the result

  • Open the optimized file next to the original and compare them visually at several sizes.
  • Verify that colours, gradients and masks still look right, since aggressive path merging can occasionally change them.
  • Confirm that the title is still present if the image needs an accessible name.
  • Compare file sizes to make sure the saving is worth any risk.

Automate it

Add SVGO to your build step or a pre-commit hook so every icon is optimized consistently. Commit both the configuration and the optimized files, so teammates and automated builds produce the same result. Then, when you add a new icon, there is no extra thing to remember.

Common questions

Does SVGO change how an image looks? Not in normal use, but aggressive settings can alter complex gradients or filters, so compare before and after. Is it safe to run SVGO on every file in a project? Run it on a copy of the folder first, review the differences, and commit the results once you are satisfied. Should I optimize SVGs that I serve with gzip or Brotli? Yes, because the two techniques are complementary: SVGO removes unnecessary content, and compression shrinks what remains. What if an icon needs to be recolored by CSS? Avoid options that inline styles or convert colours into fixed values, and use currentColor in the source so the fill can follow your page styles.

Sources