一、问题背景
当多个 SVG 使用相同的id或class时,就有可能引发样式相互干扰,导致出现不可预期的结果。比如下面这个 SVG 字符串示例:
<svg version='1.1' id='开始' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 48 48' style='enable-background:new 0 0 48 48;' xml:space='preserve'>
<style type='text/css'>.st0{fill:#231F20;}</style>
<g>
<path class='st0' d='M33.7,23l-8.1-4.6l-8.1-4.6c-0.2-0.1-0.3-0.1-0.5-0.1c-0.5,0-1,0.4-1,1l0.1,9.3l0.1,9.3c0,0.6,0.5,1,1,1c0.2,0,0.3,0,0.5-0.1l8-4.7l8-4.7C34.3,24.3,34.3,23.4,33.7,23z M24.7,27.7l-6.5,3.8L18.1,24l-0.1-7.5l6.6,3.7l6.6,3.7L24.7,27.7z'/>
<path class='st0' d='M24,1C11.3,1,1,11.3,1,24c0,12.7,10.3,23,23,23c12.7,0,23-10.3,23-23C47,11.3,36.7,1,24,1z M24,45C12.4,45,3,35.6,3,24C3,12.4,12.4,3,24,3c11.6,0,21,9.4,21,21C45,35.6,35.6,45,24,45z'/>
</g>
</svg>
<svg version='1.1' id='结束' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 48 48' style='enable-background:new 0 0 48 48;' xml:space='preserve'>
<style type='text/css'>.st0{fill:red;}</style>
<g>
<path class='st0' d='M33.7,23l-8.1-4.6l-8.1-4.6c-0.2-0.1-0.3-0.1-0.5-0.1c-0.5,0-1,0.4-1,1l0.1,9.3l0.1,9.3c0,0.6,0.5,1,1,1c0.2,0,0.3,0,0.5-0.1l8-4.7l8-4.7C34.3,24.3,34.3,23.4,33.7,23z M24.7,27.7l-6.5,3.8L18.1,24l-0.1-7.5l6.6,3.7l6.6,3.7L24.7,27.7z'/>
<path class='st0' d='M24,1C11.3,1,1,11.3,1,24c0,12.7,10.3,23,23,23c12.7,0,23-10.3,23-23C47,11.3,36.7,1,24,1z M24,45C12.4,45,3,35.6,3,24C3,12.4,12.4,3,24,3c11.6,0,21,9.4,21,21C45,35.6,35.6,45,24,45z'/>
</g>
</svg>
若页面上存在多个类似这样的 SVG,且它们的id或者class相同,那么其样式很可能会相互影响,致使显示结果不尽人意。
虽然是两个svg,但是第二个svg的样式 st0会把第一个svg的样式覆盖,如果用了mask,使用了id,也会有这个的问题
二、解决方案
为解决这一问题,可以采用img元素来引入 SVG 字符串。具体步骤如下:
- 首先确保 SVG 字符串中含有xmlns=‘http://www.w3.org/2000/svg’,这是 SVG 的命名空间声明,能确保 SVG 被正确识别和渲染。
- 创建一个Blob对象,将 SVG 字符串作为参数传入,并指定 MIME 类型为image/svg+xml。
- 运用URL.createObjectURL方法创建一个数据 URL,将Blob对象作为参数传递给它。
- 获取页面上的img元素,并将数据 URL 设置为img元素的src属性。以下是用 JavaScript 实现的代码示例:
<!DOCTYPE html>
<html>
<body>
<img id="myImage" />
<script>
const svgString = `<svg version='1.1' id='开始' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 48 48' style='enable-background:new 0 0 48 48;' xml:space='preserve'>
<style type='text/css'>.st0{fill:#231F20;}</style>
<g>
<path class='st0' d='M33.7,23l-8.1-4.6l-8.1-4.6c-0.2-0.1-0.3-0.1-0.5-0.1c-0.5,0-1,0.4-1,1l0.1,9.3l0.1,9.3c0,0.6,0.5,1,1,1c0.2,0,0.3,0,0.5-0.1l8-4.7l8-4.7C34.3,24.3,34.3,23.4,33.7,23z M24.7,27.7l-6.5,3.8L18.1,24l-0.1-7.5l6.6,3.7l6.6,3.7L24.7,27.7z'/>
<path class='st0' d='M24,1C11.3,1,1,11.3,1,24c0,12.7,10.3,23,23,23c12.7,0,23-10.3,23-23C47,11.3,36.7,1,24,1z M24,45C12.4,45,3,35.6,3,24C3,12.4,12.4,3,24,3c11.6,0,21,9.4,21,21C45,35.6,35.6,45,24,45z'/>
</g>
</svg>`;
// 创建 Blob 对象
const blob = new Blob([svgString], { type: "image/svg+xml" });
// 创建 DataURL
const dataUrl = URL.createObjectURL(blob);
// 获取页面上的 img 元素
const imgElement = document.getElementById("myImage");
// 设置 img 元素的 src
imgElement.src = dataUrl;
</script>
</body>
</html>
通过这种方式,我们能够将 SVG 以图像的形式引入到页面中,从而有效避免多个 SVG 之间的样式污染问题。
三、总结
在使用 SVG 时,我们需要警惕样式污染的问题。通过使用img元素引入 SVG 字符串,并确保 SVG 字符串中包含正确的命名空间声明,我们可以成功避免样式污染,确保 SVG 在页面上正确显示。这种方法简单而有效,适用于各种前端开发场景。