Preventing SVG ID Collisions When Inlining Icons in HTML
Duplicate SVG IDs break inlined icons. Enable SVGO's prefixIds plugin in your v3+ config to rename internal IDs and update references, keeping every icon rendering correctly in one document.
28 Jul 2025, 19:46 UTC

The Problem: Duplicate SVG IDs Break Inlined Icons
You inline two SVG icons into the same HTML page. Each icon uses an internal id="clipA" for a clip path. In isolation they look correct. Together, one icon loses its shape or renders with the wrong fill. The cause is duplicate IDs: in a single HTML document, an id must be unique, and the browser resolves references such as url(#clipA) to the first matching element in the DOM, ignoring the second.
The Thesis: Rename IDs During Optimization
SVGO's prefixIds plugin addresses this by renaming element IDs and updating every internal reference to match. When you inline multiple SVGs, each file's IDs become unique within the final document. The plugin is included in SVGO's preset-default, but you should enable and configure it explicitly rather than relying on preset defaults, because the generated prefix may not be predictable across builds.
How prefixIds Works
The plugin scans for id attributes and rewrites them using a prefix you provide or a default namespace. It then updates references in presentation attributes and CSS properties that point to those IDs, including clip-path, mask, fill, stroke, and filter. For example, an element with id="clipA" and a child referencing clip-path="url(#clipA)" will both change consistently.
Configuring prefixIds in SVGO v3+
SVGO version 3 moved configuration from JSON to a JavaScript or ESM file, typically named svgo.config.js. Older preset names such as full are not directly portable. Before changing your pipeline, confirm the installed version by running svgo --version in your terminal. You need write access to the project directory to create or edit the config file.
A minimal configuration enables the plugin with a custom prefix:
// svgo.config.js
module.exports = {
plugins: [
{
name: 'prefixIds',
params: {
prefix: 'icon-'
}
}
]
};
Note that SVGO v3 uses params for plugin options in some contexts, while other integrations may expect options. Check the documentation for your exact installed version if the prefix does not appear in output.
Worked Example: Optimizing an Icon Directory
Assume your project stores source icons in ./src/icons and you want optimized copies in ./dist/icons. Run SVGO from the project root, where you have write permission to the output folder:
npx svgo --config ./svgo.config.js --input ./src/icons --output ./dist/icons
Placeholders: replace ./src/icons and ./dist/icons with your actual paths. If your SVGO build uses different CLI flags, run npx svgo --help to confirm the correct option names for your version.
Expected check: open one file from ./dist/icons. If the source contained id="clipA", the output should contain a renamed ID such as id="icon-clipA", and every url(#clipA) reference should now read url(#icon-clipA). If references still point to the old ID, the plugin did not run or the config was not loaded.
Relevant risk: if an external stylesheet contains a rule like #clipA { display: none }, that rule will no longer match after optimization. You must update external CSS and JavaScript manually or avoid referencing SVG internals from outside the markup.
Limitations and Trade-offs
Prefixing is not universally safe. It does not rewrite IDs referenced by external stylesheets or JavaScript. It can also break SVG sprites or <use> elements that rely on stable, cross-file IDs when each source SVG is optimized independently. If your architecture depends on a shared sprite with predictable IDs, test the output before deploying.
Another trade-off is payload size. Longer IDs add bytes to each file. Pairing prefixIds with cleanupIds can reduce output size by removing unreferenced IDs before or after renaming, but plugin ordering matters. A conservative approach is to remove unused IDs first, then prefix the survivors, and verify the result against your installed SVGO version's documentation.
Actionable Closing: Verify in a Browser
To confirm the fix works, create a test HTML file that inlines two SVGs which originally shared an ID, such as clipPath id="a". Open the file in a browser. If both icons render correctly, the prefixing succeeded. If one icon is malformed, inspect the inlined markup for consistent ID renaming and reference updates. This check requires no special permissions beyond the ability to open a local HTML file.