SVG and XML Minification: Cut File Size Without Breaking Graphics
Learn what safe XML minification removes, what SVGO changes in an SVG, how to avoid broken viewBoxes and IDs, and how compression changes the maths.
.jpg)
Few file formats are as easy to bloat as SVG, and few are as easy to shrink. An icon exported from a design tool can weigh ten times what the same icon needs, and a hand-maintained XML file can carry thousands of bytes of indentation that no program will ever read. Minification fixes both, but the two formats need different handling. XML minification is mostly about whitespace and a few optional constructs. SVG minification is a deeper kind of optimisation, because an SVG is not just text: it is drawing instructions, and those can be rewritten into a shorter form that draws exactly the same picture.
This guide covers both. It explains what a safe XML minifier removes and what it must never touch, why SVG exports are so heavy, what an optimiser such as SVGO actually does to your file, how to configure it so that it does not break your graphics, how compression changes the maths, and how to deliver the result. Along the way you will see real measurements rather than vague promises, a checklist for the things that most often go wrong, and a workflow you can follow in the browser with the DevUtilX tools or in a build pipeline.
How SVG and XML are related
SVG is an application of XML. Every SVG file is a well-formed XML document, which means the rules in our guide to XML formatting and structure apply to it without exception: one root element, matching tags, quoted attributes, escaped special characters and namespaces declared where they are used. That relationship matters here for two reasons.
First, any generic XML tool can process an SVG file. A whitespace minifier written for XML will happily shrink an SVG, and an XML validator will tell you if it is malformed.
Second, SVG adds meaning on top of XML syntax, and a generic XML tool knows nothing about that meaning. It cannot tell that M 12.000000,2.000000 and M12 2 describe the same point, that a <g> element wrapping a single shape does nothing, that an id is never referenced, or that an editor's private namespace can be deleted without changing a pixel. Only an SVG-aware optimiser knows these things. That is why this article treats the two formats together but separately: the first half builds the general XML foundation, and the second half goes into what is specific to vector graphics.
If you want the formatting side of SVG before the minification side, our guide to SVG formatting and editing explains the structure of an SVG file, the viewBox, and how to read path data. Formatting and minification are opposites in terms of layout, but they work well together: format a file so you can understand and edit it, then minify the final version for delivery.
What XML minification means
XML minification is the removal of characters that carry no information, so that the document is smaller but parses to exactly the same data. The XML 1.0 specification defines which characters are significant, and a careful minifier works strictly inside those rules. Here is what it can remove, from the safest to the most debatable.
Comments
Comments, written <!-- like this -->, are for human readers. A parser can report them, but almost no application uses them. Removing them is safe in nearly every case. The exceptions are comments used as markers by another tool, such as a build step that inserts content after a particular comment, and licence headers that you are required to keep. If your file includes a licence comment, configure the minifier to preserve comments that begin with a particular marker, or keep the licence in a separate file.
Insignificant whitespace between elements
In data-oriented XML, such as a sitemap, a feed or a configuration file, the line breaks and indentation between elements exist only for readers. Removing the whitespace between a closing tag and the next opening tag does not change the data model. This is the biggest saving in most XML files, and it is the one most minifiers apply by default.
The XML declaration
The line <?xml version="1.0" encoding="UTF-8"?> is optional in XML 1.0 when the document is encoded in UTF-8 or UTF-16 and uses version 1.0. A minifier can drop it. However, you should keep it if you are not sure of the encoding, if the file uses another encoding, or if a downstream consumer expects it. Many strict parsers and some protocols, such as certain SOAP stacks, handle it better when it is present. Because the declaration is only about 38 bytes, there is rarely a good reason to remove it.
Redundant namespace declarations and empty elements
Where an element is empty, <br></br> can become <br/>. A namespace that is declared but never used by any element or attribute can be removed, which is common in SVG exports and in documents generated by tools that declare every namespace they know. This is not strictly whitespace minification, so it requires a tool that understands namespaces, and it should be applied with care. If the document has a schema that refers to those namespaces, or if a consumer looks for them by prefix, the document can break.
Attribute formatting
Attribute order does not matter in XML, and neither does the whitespace between attributes beyond a single separating space. A minifier reduces runs of whitespace between attributes to one space. It cannot remove the quotes around attribute values, unlike HTML, where unquoted values are sometimes allowed. In XML, quotes are mandatory.
What XML minification must never do
The skill in XML minification is knowing what to leave alone. These are the constructs that cause real damage when a minifier gets them wrong.
Mixed content
Mixed content is text interleaved with elements, as in a paragraph with inline markup:
<p>Install the <code>svgo</code> package, then run it on <em>every</em> file.</p>
Here, the spaces between words and tags are part of the text. A minifier that removed all whitespace between a closing tag and the next character would glue "svgo" to "package" and "run" to "it". The rule is simple: only remove whitespace that sits in a text node consisting purely of whitespace, and only in elements where the content model is element-only. Document-oriented XML, such as DocBook, XHTML, DITA and many publishing formats, is full of mixed content, and aggressive whitespace removal is dangerous there.
Elements that declare whitespace as significant
The reserved attribute xml:space="preserve" tells applications that whitespace inside an element must be kept. SVG <text> elements frequently use it. A correct minifier respects it, and so should you. Some formats define their own preservation rules too. In Office Open XML (the format inside .docx files), for example, a text run can carry xml:space="preserve" to keep leading and trailing spaces.
CDATA sections and text content
The text inside a CDATA section, written <![CDATA[ ... ]]>, is literal. The contents of an embedded script, a code sample or a template must not be altered. Even in ordinary text nodes, a minifier should leave the characters between words alone. Collapsing multiple spaces inside a string is a change to the data, and in some formats, such as those holding source code or preformatted text, it is a bug.
Processing instructions, DOCTYPE and entities
A document that declares a DOCTYPE with an internal subset can define entities, and the minifier needs to leave those definitions intact. Stripping a DOCTYPE from a file that uses entities will make the document fail to parse. In practice, modern formats avoid DTDs, but older enterprise XML and some publishing formats still use them.
Digitally signed and canonicalised documents
If an XML document carries a digital signature, such as an XML-DSig signature in a SAML assertion or a signed SOAP message, any change to the signed content, including whitespace, can invalidate the signature. Signed XML is typically canonicalised before signing, using a standard such as Canonical XML, and the signature verifies the canonical form. Never minify a document after it has been signed. Minify first, then sign, or leave the signed document untouched.
Schema-validated documents
Whitespace-only text nodes are usually allowed to appear in element-only content, but some schemas and some validators treat them differently, and mixed-content types treat them as data. Run the minified output through the same validator as the original. If it still passes, the change is safe for that consumer.
How much does XML minification save?
The answer depends on how deeply the file is indented and how much of it is markup versus content. As a concrete example, consider a sitemap with 200 URL entries, each with four child elements. Written the way most generators write it, with two-space indentation, the file is 35,227 bytes. With comments and inter-element whitespace removed, it is 29,997 bytes, a reduction of roughly 15 percent.
That sounds useful until you compress the files. With gzip at its highest setting, the indented version is 1,150 bytes and the minified version is 1,102 bytes. The saving is 48 bytes, or about 4 percent. The compressor had already learned that the repeated indentation is predictable and squeezed it almost to nothing. This is typical: XML is repetitive, repetitive text compresses extremely well, and whitespace is the most repetitive part of all.
The lesson is not that XML minification is useless. It is that it matters most when the file is not compressed in transit, when it is parsed repeatedly in memory, when it is stored on disk at scale, or when it is embedded in something with a hard size limit, such as a QR code, a cookie or an email. For a large sitemap served to search engines over HTTPS with compression, the real-world gain is small. Always measure the compressed size, because that is what travels over the network. The MDN guide to HTTP compression explains how servers and browsers agree on gzip or Brotli.
Why SVG files are so heavy
SVG is a different story, because SVG exports from design tools carry far more than whitespace. To see why, here is a deliberately ordinary example: a small 24 by 24 pixel icon exported from Inkscape. The drawing is three stacked chevron shapes. The file, 2,285 bytes in total, contains:
- An XML declaration and an authoring-tool comment.
- Eight namespace declarations, most of them used only by editor metadata.
- A
<defs>block with a gradient that nothing references. - A
<sodipodi:namedview>element that stores the editor's window size, zoom level and guides. - A
<metadata>block with Creative Commons RDF information. - Two nested groups, one carrying a
translate(0,0)transform that does nothing. - Three
<path>elements, each with anidthat no CSS or script uses, a longstyleattribute, and path data written with six decimal places for every coordinate.
None of that affects how the icon looks. The shapes are three simple polylines. Once the junk is stripped, they can be described in about two hundred bytes.
The usual sources of bloat
Almost every exported SVG carries some mix of the following.
Editor metadata and private namespaces. Inkscape adds sodipodi: and inkscape: elements and attributes. Illustrator adds its own data, including data-name attributes and i: namespaces in older exports. Sketch, Figma and Affinity add comments, empty descriptions and generated names. These help the editor reopen the file for editing, but a browser ignores them.
Comments and generator notes. "Generator: Adobe Illustrator" and similar lines.
Unnecessary precision. Many tools write coordinates with six or more decimal places. For an icon displayed at 24 pixels, a coordinate precise to one millionth of a unit is meaningless. Rounding to two or three decimals changes nothing the eye can see.
Verbose path syntax. Path data can use absolute or relative commands, can repeat a command letter when it could be omitted, and can include spaces and commas where none are required. M 12.000000,2.000000 L 2.000000,7.000000 and M12 2 2 7 mean the same thing.
Redundant groups and transforms. A <g> with a single child and no attributes does nothing. A transform of translate(0,0) or scale(1) does nothing. Tools frequently produce such wrappers.
Default values written explicitly. fill-opacity="1", stroke-opacity="1" and stroke-linecap="butt" are the defaults. Writing them costs bytes without changing the result.
Inline styles instead of attributes. style="fill:none;stroke:#000000" is longer than fill="none" stroke="#000", and when several paths share the same style, the repetition adds up.
Generated IDs. id="path12", id="g10" and so on, which nothing refers to.
Unused definitions. Gradients, filters, clip paths and symbols that were defined but never used.
Hidden and empty elements. Shapes with zero size, elements with display:none, empty text nodes and empty groups.
Embedded raster images. An SVG can embed a PNG or JPEG as a base64 string. These are enormous compared to vector shapes. If you find one, consider whether the graphic should be vector at all.
Long colour values. #000000 can be #000, and rgb(255,0,0) can be red.
What an SVG optimiser does
An SVG optimiser is a program that parses the file into a tree, applies a series of transformations, and prints the result back out compactly. The best-known one is SVGO, an open-source Node.js tool that is also built into many other products. It is organised as a list of plugins, each performing one kind of optimisation, and a default preset enables the ones considered safe for most files. Here is what happens when it processes the Inkscape icon described above.
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2 2 7l10 5 10-5zM2 17l10 5 10-5M2 12l10 5 10-5" style="fill:none;stroke:#000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/></svg>
That is 256 bytes, down from 2,285, a reduction of 88.8 percent. Look at what changed:
- The XML declaration, comment, metadata and editor namespace elements are gone.
- The unused gradient and the empty
defsare gone. - The two wrapper groups and the no-op transform are gone.
- The three separate paths with identical styling were merged into one path with a single style.
- The coordinates were rounded and the commands were converted to the shortest equivalent form, using relative commands where they are shorter and dropping repeated command letters.
- The colour
#000000became#000. - The unreferenced IDs were removed.
- The widths
24.000000became24.
The picture is identical. You can open both files and compare them pixel for pixel.
For comparison, a plain whitespace minifier that removes comments and line breaks brings the same file to 1,881 bytes, a saving of about 18 percent. The remaining 1,600 bytes are editor metadata, redundant structure and excessive precision, which only an SVG-aware tool can safely remove. This is the central point of this article: for XML in general, minification is a small gain, but for SVG, optimisation is a large one.
The compressed sizes tell the same story
Gzipped at its highest setting, the original is 810 bytes, the whitespace-minified version is 725 bytes, and the SVGO output is 197 bytes. The ratio between the original and the optimised file is smaller after compression than before (about 4 to 1 compared with about 9 to 1), because compression already handles the repeated structure well. But the optimised file is still far smaller, and an optimised file also has less to parse and less to keep in memory. If a page uses hundreds of icons, the difference adds up.
These figures come from a small icon. Larger illustrations, maps and charts have more to gain, because they contain more path data, and path data is where precision and syntax savings accumulate.
The main SVGO optimisations in detail
Understanding what each family of optimisation does helps you decide which ones to keep and which to turn off.
Cleaning up structure
Plugins in this family remove comments, metadata, editor data, empty attributes, empty containers, hidden elements and unused definitions. They also collapse groups that serve no purpose and move attributes up from a group's children when they all share the same value. These are the safest and the most productive. The only cases that need care are elements you reference from outside the file, which we cover in the section on what can break.
Cleaning up attributes and styles
These convert inline style declarations into presentation attributes, remove attributes that equal their default values, shorten colour values and trim numbers. Converting styles to attributes can matter if you depend on CSS specificity: a presentation attribute has lower priority than any CSS rule, while an inline style has higher priority than most. If your page's CSS targets the SVG's internals, test the result.
Numeric precision
SVGO rounds numbers to a configurable number of decimal places, with a default of three. For icons on a 24 by 24 grid, two decimals are usually indistinguishable. For large maps with coordinates in the thousands, the same precision may be perfectly fine, because the absolute error is still tiny compared with the drawing's size. For very small coordinate systems, such as a viewBox of 0 0 1 1, three decimals might be too coarse, and you should raise the precision. The failure mode of too-low precision is visible: shapes appear slightly distorted, curves lose their smoothness, or neighbouring shapes show hairline gaps.
Path data optimisation
Path data is usually the largest part of an SVG, and the most complex one to optimise. The SVG 2 specification defines the path mini-language, and an optimiser works with it as follows:
- It converts between absolute and relative commands, choosing whichever is shorter for each segment.
- It uses shorthand commands where possible:
HandVfor horizontal and vertical lines,SandTfor smooth curves that continue the previous control point. - It drops repeated command letters, since
L 10 10 L 20 20can be writtenL 10 10 20 20. - It removes unnecessary separators: a space before a minus sign is not needed, as in
10-5, and a leading zero can be omitted, as in.5. - It converts straight curves into lines, and arcs that are actually circles into simpler forms, where it can prove they are equivalent.
- It merges adjacent paths that share the same attributes into one path, which is what happened to the three chevrons above.
Merging paths is powerful but needs care. If you intend to animate or style the shapes separately, merging them destroys the structure you need. SVGO's plugin for merging paths can be disabled for exactly that reason.
Transforms
An optimiser can apply transforms to the coordinates directly, so that transform="translate(10,10)" on a path is baked into the path data and the attribute is removed. It can also simplify chains of transforms into a single matrix or shorter form. The usual caution is that baking a transform into a shape that has a stroke or a gradient can alter how they behave, so the optimiser has rules for when it is safe.
IDs
Unreferenced IDs are removed, and referenced IDs are shortened, so that id="linear-gradient-background" might become id="a", with every reference updated to match. This saves bytes, but it makes collisions possible, and breaks any external reference to the original ID, as we see next.
What can break, and how to prevent it
Because SVG optimisation rewrites a file, it can occasionally change behaviour. Almost every problem falls into one of the following categories, and almost every one is preventable by turning off a single plugin.
Removing the viewBox
Some optimisation settings remove the viewBox attribute when width and height are present, since the two can sometimes express the same thing. But the viewBox is what lets the graphic scale to any size. An icon without one will not scale when you set its size with CSS, and may be cropped or displayed at the wrong size. Always keep the viewBox. In SVGO, this means disabling the removeViewBox plugin, which was in earlier default presets and is now off by default in recent versions, but is worth checking in any older configuration you inherit.
Breaking external references to IDs
If your CSS, JavaScript or animation code refers to an element inside the SVG by its id, the optimiser will not know unless it can see the page. When it removes or renames an ID, the selector no longer matches, and the animation or style silently stops working. Common cases are: CSS rules like #logo-path { fill: red }, scripts that call getElementById, SMIL animations that reference targets by ID, and <use href="#shape"> references in sprites. If you rely on any of these, either disable the ID cleanup plugin for that file, or configure it to preserve specific IDs.
IDs colliding when several SVGs are inlined on one page
This is the reverse problem. Two different SVGs, each with a gradient called a after shortening, will conflict when both are inlined in the same HTML document, because IDs must be unique within a document and the second gradient will resolve to the first one. The symptom is a graphic that shows the wrong colours, or no fill at all. The fix is to give each file a unique prefix. SVGO's prefixIds plugin does this by adding a prefix based on the file name or a value you supply.
Removing the title and desc elements
The <title> and <desc> elements give a graphic an accessible name and description. An optimiser may treat them as removable metadata. If your graphics convey information, keep them, because screen readers rely on them. Decorative icons should instead be hidden from assistive technology with aria-hidden="true". Check that your configuration preserves accessibility attributes such as role, aria-label and aria-labelledby.
Breaking text
SVG <text> elements depend on whitespace and font settings. Aggressive whitespace removal can change spacing, and removing font-related attributes can change rendering when the font is not the default. If your SVG contains live text rather than outlines, test it. Converting text to outlines before optimising avoids the issue, but removes the ability to select, search and translate the text.
Collapsing groups that scripts or styles need
A group with no attributes is useless to the browser, but it may be the hook your script uses to find a set of shapes. Optimisers collapse it. If you need the grouping, give it an id or a class that is preserved, or disable group collapsing.
Inline styles and CSS in <style> blocks
An SVG can include a <style> element, and an optimiser can minify the CSS inside it and merge or remove rules. It can also drop rules it believes are unused. If your style rules rely on classes that are added later by JavaScript, or on media queries for dark mode, the optimiser might decide they are unused and delete them. A common example is a dark-mode rule such as @media (prefers-color-scheme: dark) { .fg { fill: white } }. Test the file with each state that matters.
Removing hidden elements that are shown later
An element with display:none or opacity="0" might be revealed by an animation or an interaction. An optimiser can remove it as invisible. If your graphic is animated or interactive, check that these elements survive, or turn off the hidden-element plugin.
Over-rounding
If shapes distort or neighbouring shapes show gaps after optimisation, the precision is too low. Raise it and run the process again.
The general safeguard
For every non-trivial graphic, compare the original and the optimised version visually before shipping, at the sizes you use and in each theme. Automated visual regression tools can do this in a build, but even opening both files side by side in a browser catches most problems. And keep the original, unoptimised file as your source. Optimised files are build artefacts, not masters.
Configuring SVGO
SVGO is configured with a JavaScript file, svgo.config.js, at the root of your project. The configuration lists plugins and their options. A sensible starting point keeps the default preset, but protects the viewBox and the accessibility elements:
// svgo.config.js
module.exports = {
multipass: true, // run the plugins repeatedly until the output stops shrinking
js2svg: {
pretty: false, // set to true to emit readable output while debugging
},
plugins: [
{
name: "preset-default",
params: {
overrides: {
// Keep the viewBox so the graphic can scale.
removeViewBox: false,
// Keep <title> and <desc> for accessibility.
removeTitle: false,
removeDesc: false,
},
},
},
// Optional: make IDs unique when inlining many SVGs in one page.
"prefixIds",
],
};
Run it from the command line:
# Optimise one file
npx svgo icon.svg -o icon.min.svg
# Optimise a whole folder, in place
npx svgo -f ./icons -o ./icons-min
# Use a specific configuration file
npx svgo --config svgo.config.js icon.svg
Or call it from Node.js, which is the usual choice in build scripts:
import { optimize } from "svgo";
import { readFileSync, writeFileSync } from "node:fs";
const input = readFileSync("icon.svg", "utf8");
const result = optimize(input, { path: "icon.svg", multipass: true });
writeFileSync("icon.min.svg", result.data);
console.log(`${input.length} -> ${result.data.length} bytes`);
Two options deserve explanation. multipass: true repeats the whole plugin pipeline until nothing more can be removed, since one optimisation often exposes another. It costs a little extra time and is worth enabling for production builds. The pretty option controls whether the output is formatted, which is useful when you need to inspect what the optimiser produced.
If you work in a framework, you probably do not need to call SVGO directly. Tools such as the Vite and webpack SVG plugins, and SVGR for React, run it as part of the build. The DevUtilX SVG to JSX tool is useful for the step after optimisation, converting an SVG into a React component.
Step-by-step: minify SVG and XML with DevUtilX
For a one-off job, without installing anything, you can do the work in the browser. DevUtilX has three tools relevant to this guide, and each processes your input locally, so nothing is uploaded.
To minify an SVG file:
- Open the SVG Minifier or the SVG Optimizer.
- Paste the SVG code into the input editor.
- Run the tool and compare the output size with the original.
- Paste the result into a test HTML page, or open it directly in a browser, and compare it with the original visually.
- Copy the optimised code into your project.
Use the minifier when you want a conservative whitespace-and-comment reduction, and the optimiser when you want deeper structural and path optimisation. If something looks wrong in the optimised output, go back to the minifier, which makes fewer changes.
To minify an XML file:
- Open the XML Minifier.
- Paste your XML into the input editor.
- Run the tool and check the size reduction.
- If the document might contain mixed content, review the output for missing spaces before using it.
- Copy the result.
To make minified code readable again:
Use the SVG Formatter for SVG, or the XML Beautifier for XML. Neither can restore comments or original names that were removed, so keep your source files.
If a tool reports an error, the input is probably not well-formed. Look for an unclosed tag, an unescaped ampersand, mismatched case in tag names or an undeclared namespace prefix, and use the XML Validator to find the position.
Compression and delivery
Minification is the first step. Delivery is the second, and it determines how much of the saving reaches your users.
Compress text responses
SVG and XML are text, so they compress very well. Make sure your server or CDN sends them with Brotli or gzip. Many servers compress only a list of MIME types, and SVG's type, image/svg+xml, is sometimes missing from the default list, so SVG files are sent uncompressed while HTML, CSS and JavaScript are compressed. Check in your browser's network tab: the response headers should include content-encoding: br or content-encoding: gzip. In nginx, for example, you can make sure the type is listed:
gzip on;
gzip_types image/svg+xml application/xml text/xml application/rss+xml application/atom+xml;
The same applies to Apache and to most CDNs, where it is usually a setting in the dashboard.
Pre-compressed SVGZ
A gzip-compressed SVG file is conventionally given the extension .svgz. A server can send it with the Content-Encoding: gzip header. In practice, on-the-fly compression by the server handles the same case with less effort, and precompression is mainly useful for static hosting where you want maximum compression at build time, with Brotli at the highest level.
Choosing how to include the SVG
How you put the graphic into the page affects both size and capability.
| Method | Styleable from page CSS | Cached separately | Counts toward HTML size | Best for |
|---|---|---|---|---|
| Inline in HTML | Yes | No | Yes | A few small icons you restyle or animate |
<img src="file.svg"> |
No | Yes | No | Logos and illustrations |
CSS background-image |
No | Yes | No | Decorative graphics |
<use> with an SVG sprite |
Partly, through inherited properties | Yes | No | Large icon sets reused across pages |
| Data URI in CSS | No | With the CSS | Adds to the CSS | Very small graphics that must not cost a request |
Inlining many large SVGs makes every page heavier, because inline SVG cannot be cached between pages. A sprite, one file containing many <symbol> definitions that each page references with <use>, gives you caching and a single request. Minify and optimise the sprite as a whole, and keep IDs stable, since the references depend on them.
Cache with fingerprints
Give files a content hash in the file name, such as icons.3f9a1c.svg, and serve them with a long Cache-Control lifetime. Browsers will then reuse them without asking, and a changed file gets a new name automatically.
Consider whether SVG is the right format
SVG excels at icons, logos, diagrams and simple illustrations. It is a poor choice for photographs and for very complex artwork with tens of thousands of paths, which can be larger and slower to render than a raster image. If an optimised SVG is still hundreds of kilobytes, consider a WebP or AVIF image instead.
Security: SVG and XML are not just data
Both formats can carry active content, and minification does not make a file safe.
SVG can contain scripts. A <script> element and event handler attributes such as onload are valid SVG, and they run when the file is opened directly or inlined into a page. An SVG loaded through an <img> tag cannot run scripts, but the same file opened as a document, or placed inline, can. If your site accepts SVG uploads from users, treat them as untrusted. Sanitise them with a library designed for the task, such as DOMPurify with its SVG profile, or serve them from a separate domain with a restrictive Content Security Policy. Do not assume an optimiser removes scripts. SVGO has a plugin for removing scripts, but it is not part of the default preset and should not be your only defence.
XML parsers can be abused. XML supports external entities, which let a document ask the parser to read a local file or fetch a URL. This is the basis of XML External Entity (XXE) attacks. A related attack, sometimes called the billion laughs attack, uses nested entity definitions to make a small document expand into gigabytes of memory. When you parse XML from an untrusted source, disable DTD processing and external entities in your parser. The OWASP XML External Entity Prevention Cheat Sheet lists the settings for every common language.
Do not put secrets in either format. Minified SVG and XML are as readable as any other text once passed through a formatter.
Tools for SVG and XML minification
Beyond the browser tools, these are widely used.
For SVG:
- SVGO: the standard optimiser, plugin-based, with a command line and a Node.js API.
- SVGOMG: a browser-based interface to SVGO, useful for seeing the effect of each setting on a file before committing to a configuration.
- Scour: a Python-based SVG optimiser used by Inkscape's "Optimized SVG" export.
- svgcleaner: a fast optimiser written in Rust, aimed at removing editor data and applying safe transformations.
For XML:
xmllint: part of libxml2, it can check well-formedness and, with--noblanks, remove ignorable whitespace.- Language libraries:
lxmlandxml.etreein Python,System.Xmlin .NET andDocumentBuilderin Java can all parse and re-serialise a document without formatting, producing a compact output. - General-purpose minifiers: several multi-format minifier libraries and command line tools handle XML along with HTML, CSS and JSON.
A short Python example shows how to minify data-style XML safely by parsing and re-serialising it. Because it works on the parsed tree, it cannot damage strings or quoting, and it discards whitespace-only text nodes.
from lxml import etree
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True)
tree = etree.parse("sitemap.xml", parser)
tree.write(
"sitemap.min.xml",
encoding="utf-8",
xml_declaration=True,
pretty_print=False,
)
The remove_blank_text option removes whitespace-only text nodes. For files with mixed content, do not use it, because it can drop significant spaces in some cases.
A checklist for shipping minified SVG and XML
Use this list before you publish a file.
- Keep the source. The readable original is the master. The minified file is generated.
- Validate the original. A minifier cannot fix invalid input, and may hide the problem.
- Check the format's rules. Is there mixed content,
xml:space, a signature or a schema? If so, be conservative. - For SVG, protect what you need. Keep the
viewBox, accessibility elements and any IDs that scripts or styles reference. - Run the optimiser or minifier.
- Compare visually at the sizes and in the themes you ship.
- Validate the output with the same validator as the input.
- Measure the compressed size, not just the raw size.
- Confirm compression is enabled for the file's MIME type on your server.
- Add content hashes and long cache lifetimes.
- Sanitise anything that came from users.
Common mistakes
- Minifying a signed document. The signature will no longer verify.
- Removing the
viewBox. The graphic stops scaling. - Collapsing whitespace in mixed content. Words run together.
- Breaking ID references. Animations, styles and sprites silently stop working.
- ID collisions after shortening. Two inlined SVGs fight over the same gradient.
- Over-rounding coordinates. Curves wobble and thin gaps appear.
- Expecting a large saving on small, already-compact XML. Check the compressed size first.
- Forgetting to enable compression for
image/svg+xml. The optimised file still travels uncompressed. - Trusting the optimiser for security. Minification is not sanitisation.
- Editing minified files by hand. Change the source and rebuild.
- Optimising without looking at the result. A thirty-second visual check prevents most surprises.
Best practices
- Use a general XML minifier for data-style XML, and an SVG-aware optimiser for SVG. They solve different problems.
- Automate it in the build. Run SVGO on your icons and illustrations as a build step, with a configuration committed to the repository.
- Prefer a conservative configuration first, then enable more aggressive plugins one at a time while checking the results.
- Design with optimisation in mind. Use a consistent grid, simple shapes, and as few points as the shape needs. A graphic that is simple at the source is smaller after optimisation than one that is complex.
- Outline or subset text deliberately. Decide for each graphic whether text must be live.
- Use
currentColorfor icons that should follow the surrounding text colour, so one file serves every theme. - Provide accessible names for meaningful graphics and hide decorative ones.
- Serve with Brotli or gzip, and cache with hashed names.
- Measure. Track the total size of your icons and graphics over time, and treat a sudden jump as a regression.
FAQ
Is minified SVG still valid SVG?
Yes. A good optimiser only produces valid, equivalent markup. Whitespace removal, shorter path syntax and removed metadata all stay within the specification.
Will optimising an SVG change how it looks?
It should not. With sensible settings the rendering is identical. Problems come from removing the viewBox, breaking ID references, rounding too aggressively or removing elements that scripts or animations reveal later, so compare the result visually.
How much smaller will my SVG be?
It depends on the source. In the example in this article, an Inkscape icon dropped from 2,285 bytes to 256, a reduction of nearly 89 percent. Files that were already exported as clean, minimal SVG may shrink by only a few percent. Files with embedded metadata, high precision and redundant structure shrink the most.
Do I still need to minify if I use gzip or Brotli?
Yes, for SVG. Compression narrows the gap, but the optimised file in our example was still about four times smaller after gzip than the original. For plain XML with simple indentation, the gain after compression can be small, so it is worth measuring before spending effort.
Can I minify an XML file that contains text with inline tags?
Be careful. Collapsing whitespace in mixed content changes the text. Use a minifier that only removes whitespace-only nodes in element-only content, or skip minification for that file.
Should I remove the XML declaration?
It is optional for UTF-8 documents, but it costs only a few bytes and some parsers and protocols expect it. In most cases, keep it.
What happens to my comments?
Both kinds of tool remove them by default. If you need a licence notice, configure the tool to preserve it, or keep the licence in a separate file.
Is it safe to minify SVG that comes from users?
Minification does not make an SVG safe. SVG can contain scripts, so sanitise untrusted files with a dedicated library and serve them with a restrictive Content Security Policy.
Can I get my original SVG back after optimising?
No. Editor data, comments, original IDs and precision are discarded. A formatter restores the layout, but not what was removed. Always keep the source.
Why does my SVG look different after optimising?
Look first at the viewBox, at rounding precision, at removed or renamed IDs and at removed hidden elements. Turning off the matching optimisation usually solves it.
Is it safe to paste SVG or XML into an online tool?
Only if the tool runs entirely in your browser. DevUtilX processes your input locally and does not upload it, but you should never paste secrets or confidential data into any tool without checking.
Conclusion
SVG and XML share a syntax, but they reward different approaches. For data-style XML, minification means removing whitespace and comments safely, avoiding mixed content, signed documents and anything declared whitespace-significant, and then measuring the result after compression, where the gain is often modest. For SVG, optimisation is a far bigger opportunity: stripping editor metadata, simplifying structure, rewriting path data and rounding numbers can cut a file by close to ninety percent, as the example in this article showed, provided you protect the viewBox, accessibility elements and referenced IDs.
Treat the readable file as your source of truth, automate the optimisation in your build, compare the output visually, serve it compressed with long cache lifetimes, and sanitise anything that comes from users. For a quick one-off job, try the SVG Minifier, the SVG Optimizer or the XML Minifier. To go deeper into the structure behind these files, read our guides on XML formatting and structure and SVG formatting and editing, and see how the same ideas apply to other formats in our guides to JSON minification and CSS minification.
Further reading
Try the tools
Optimize and minify your SVG files to ensure better web performance. This tool removes redundant information and unnecessary code, resulting in smaller file sizes and faster rendering times for your graphics.
Reduce the size of your XML documents by removing all unnecessary whitespace and formatting. This tool is essential for optimizing data transfer and storage without affecting the data's integrity or structure.
Minify and optimize your SVG code for web use. This tool removes unnecessary data and attributes from your SVG files, resulting in smaller file sizes and faster rendering, improving website performance.
Format your SVG code with proper indentation and a clean tag structure. This tool helps in making your SVG files more readable and easier to manage for web development projects, ensuring consistency.
Format your XML documents with proper indentation and a clear, hierarchical structure. This tool is essential for improving the readability and maintainability of complex XML data files, making them easier to debug.
.jpg)
.jpg)
.jpg)