Describe the bug
When applied to <foreignObject> content, the convertStyleToAttrs plugin can break rendering. Inside <foreignObject>, the children are typically HTML elements (XHTML namespace), not SVG. Converting their inline style declarations into individual attributes is not valid in HTML, so the styling is lost.
Here is an SVG to reproduce:
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_29872_18151)">
<rect width="200" height="200" fill="#0E60D4"/>
<foreignObject x="45.9956" y="82.2183" width="185.415" height="152.969"><div xmlns="http://www.w3.org/1999/xhtml" style="backdrop-filter:blur(11.91px);clip-path:url(#bgblur_2_29872_18151_clip_path);height:100%;width:100%"></div></foreignObject>
<g>
<circle opacity="0.9" cx="144" cy="142" r="45.5" fill="#1368CE" stroke="white" stroke-width="5"/>
<path d="M160.759 117.1L170.553 125.114L138.104 164.796L117.283 147.319L125.748 137.913L136.713 146.51L160.759 117.1Z" fill="white"/>
</g>
</g>
<defs>
<clipPath id="bgblur_2_29872_18151_clip_path" transform="translate(-45.9956 -82.2183)"><rect x="68.9121" y="115.873" width="64.1024" height="11.7216" rx="5.86081" transform="rotate(-9.64387 68.9121 115.873)"/>
</clipPath>
</defs>
</svg>
To Reproduce
- Save the SVG above to a file.
- Optimise it with SVGO using the
convertStyleToAttrs plugin (it is part of the default preset).
- Open the resulting SVG in a browser.
Expected behavior
The optimised SVG should render the same as the source: the clip-path declared on the inner <div> should still apply.
Screenshots
In the broken output above, the inner <div>'s clip-path no longer applies, so the white circle behind it is no longer masked.
Desktop (please complete the following information):
- SVGO Version:
- Node.js Version:
- OS:
Additional context
The root cause appears to be that the plugin processes every element in the document, including HTML descendants of <foreignObject>. A CSS property such as clip-path is valid inside a style attribute on an HTML element, but is not a valid HTML presentation attribute, so it is silently dropped by the browser when split out. A safer behavior would be to skip any descendant of a <foreignObject> (or any element in a non-SVG namespace).
Describe the bug
When applied to
<foreignObject>content, theconvertStyleToAttrsplugin can break rendering. Inside<foreignObject>, the children are typically HTML elements (XHTML namespace), not SVG. Converting their inlinestyledeclarations into individual attributes is not valid in HTML, so the styling is lost.Here is an SVG to reproduce:
To Reproduce
convertStyleToAttrsplugin (it is part of the default preset).Expected behavior
The optimised SVG should render the same as the source: the
clip-pathdeclared on the inner<div>should still apply.Screenshots
In the broken output above, the inner
<div>'sclip-pathno longer applies, so the white circle behind it is no longer masked.Desktop (please complete the following information):
Additional context
The root cause appears to be that the plugin processes every element in the document, including HTML descendants of
<foreignObject>. A CSS property such asclip-pathis valid inside astyleattribute on an HTML element, but is not a valid HTML presentation attribute, so it is silently dropped by the browser when split out. A safer behavior would be to skip any descendant of a<foreignObject>(or any element in a non-SVG namespace).