With React + Webpack when I load multiple SVG in the same component (SVG is in the dom), ids are the same in multiple SVG :
First SVG result :
<svg width="158" height="185" xmlns:xlink="http://www.w3.org/1999/xlink" class="sc-fYxtnH hSLfWw">
<defs>
<linearGradient x1="0%" y1="100%" y2="0%" id="c">
...
Second SVG result :
<svg width="23" height="23" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path d="M22.733 1-.267-2.09z" id="c"></path>
</defs>
<g fill="none" fill-rule="evenodd">
<g>
<mask id="d" fill="#fff">
<use xlink:href="#c"></use>
</mask>
<path fill="#EA4335" fill-rule="nonzero" mask="url(#d)" d="M-1.07 4.705L8.023 11.5l3.744-3.189 12.838-2.038v-7.318H-1.07z"></path>
</g>
...
The second SVG is not rendered correctly because of that. When i remove the first SVG everything works fine.
Here is my Webpack config :
{
test: /\.svg$/,
use: [{
loader:'@svgr/webpack',
options: {
"svgoConfig": {
"plugins": [{ "cleanupIDs": true }]
}
}
}]
}
Is there something I forgot ?
Thanks
I met this problem several times. The best solution is to avoid using mask in SVG, if you are using Sketch you can flatten it to create a complete shape instead of using mask. Ids are not scoped this is why there is a problem in multiple SVG.
On SVGR part, we could maybe mitigate the problem by adding something that scope ids to the SVG file.
Imagine a foo.svg:
<svg width="23" height="23" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path d="M22.733 1-.267-2.09z" id="c"></path>
</defs>
</svg>
That will be transformed into Foo.js:
<svg width="23" height="23">
<defs>
<path d="M22.733 1-.267-2.09z" id="foo-1"></path>
</defs>
</svg>
But the problem remain when we don't have a filename (stdin) or when we have nested directories. So the best solution is to avoid ids in inline SVG.
Seems like SVGO already has this feature see #152.
sorry for jumping in on this issue - to confirm should -
{
test: /\.svg$/,
use: [{
loader:'@svgr/webpack',
options: {
"svgoConfig": {
"plugins": [{ "cleanupIDs": true }]
}
}
}]
}
work?
found this - https://github.com/svg/svgo/issues/674#issuecomment-324193597
the next one is a fix too
Hope it helps
{
test: /\.svg$/,
use: ({resource}) => ({
loader: '@svgr/webpack',
options: {
svgoConfig: {
plugins: [{
"cleanupIDs": {
"prefix": `svg${hash(relative(context, resource))}`
}
}]
}
}
})
}
Thank you @jjmax75 it works
I ran into this with linear gradients, fortunately some searching around led me here. However, this seems like a pretty disastrous default. I was able to fix mine with a simplified version of the hashing solution:
const hash = require('string-hash');
...
use: ({ resource }) => ({
loader: '@svgr/webpack',
options: {
svgoConfig: {
plugins: [{
cleanupIDs: {
prefix: `svg-${hash(resource)}`,
},
}],
},
},
}),
Is there a way we could get the default behavior to be more like this hashing solution? Seems like this is a fairly common problem.
Hi all,
Have anyone maintained this issue?
I have a problem. Don't work with render list component.
Example:
import AvatarSvgIcon from './avatar.svg';
render() {
return this.prop.users.map(user => <div key={user.id}><h1>{user.name}</h1><AvatarSvgIcon /></div>)
}
I met this problem several times. The best solution is to avoid using mask in SVG, if you are using Sketch you can flatten it to create a complete shape instead of using mask. Ids are not scoped this is why there is a problem in multiple SVG.
On SVGR part, we could maybe mitigate the problem by adding something that scope ids to the SVG file.
Imagine a
foo.svg:<svg width="23" height="23" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <path d="M22.733 1-.267-2.09z" id="c"></path> </defs> </svg>That will be transformed into
Foo.js:<svg width="23" height="23"> <defs> <path d="M22.733 1-.267-2.09z" id="foo-1"></path> </defs> </svg>But the problem remain when we don't have a filename (stdin) or when we have nested directories. So the best solution is to avoid ids in inline SVG.
Even when using the filename, hash or random to get an id, it will be repeated if
May be a note in the documentation could be useful, pointing to the Specs.
While this specification defines requirements for class, id, and slot attributes on any element, it makes no claims as to whether using them is conforming or not.
As I understand, there is no restriction to include the same ID several times, but it is not of common sense, and getElementById will match the first one in the subtree as per specs.
@gregberge do you have some recommendation?
I avoid to use ID in inline SVG, it is not reliable. Inline SVG are components, you would have the same problem in React components. Anyway there is a way to solve it. Edit by your own the SVG and use a hook to get a unique ID by component instance (example: https://gist.github.com/sqren/fc897c1629979e669714893df966b1b7).
Most helpful comment
found this - https://github.com/svg/svgo/issues/674#issuecomment-324193597
the next one is a fix too
Hope it helps