如何修改img标签src属性引入的SVG图片颜色
首先明确前提:通过<img src="xxx.svg">方式加载的SVG属于独立的外部资源,受浏览器同源策略隔离,无法直接用CSS选择器选中SVG内部的路径、形状标签修改fill/stroke属性,实际开发中可以用下面几种落地方案:
CSS filter滤镜方案(零改造成本)
这是最省事的方案,不需要修改SVG源文件,也不需要写JS,靠CSS滤镜的色彩偏移能力就能把单色SVG转成目标颜色,适合快速调整单色图标颜色的场景。
只需要根据目标颜色生成对应的滤镜参数,直接挂到img的样式上即可:.custom-svg { /* 示例:把原本纯黑的SVG转成 #1677ff 蓝色 */ filter: invert(42%) sepia(93%) saturate(1352%) hue-rotate(187deg) brightness(99%) contrast(101%); }注意这个方案只适合纯色SVG,多色SVG使用后会整体偏色;滤镜参数不需要手动计算,用在线滤镜生成工具输入目标色就能直接拿到可用代码。
CSS mask遮罩方案(单色场景推荐)
这个方案效果更可控,同样不需要修改SVG源,原理是把SVG作为遮罩层,最终显示的颜色完全由img标签的背景色决定。.custom-svg { width: 24px; height: 24px; /* 直接填写需要的颜色即可 */ background-color: #ff4d4f; /* 低版本webkit内核浏览器需要加私有前缀 */ -webkit-mask: url('./your-icon.svg') no-repeat center / contain; mask: url('./your-icon.svg') no-repeat center / contain; }注意这个方案同样只支持单色SVG:SVG里的透明区域会透出下方的页面内容,不透明区域会显示设置的背景色。
JS拉取内联替换方案(支持多色SVG修改)
如果需要修改多色SVG不同区域的颜色,可以先通过fetch拿到SVG的文本内容,把原来的img标签直接替换成内联的SVG标签,之后就能像操作普通DOM一样,用CSS任意修改SVG内部元素的颜色了。const imgEl = document.querySelector('.custom-svg'); fetch(imgEl.src) .then(res => res.text()) .then(svgStr => { const container = document.createElement('div'); container.innerHTML = svgStr.trim(); const inlineSvg = container.querySelector('svg'); // 复用原有img的类名,保证尺寸、布局样式不偏移 inlineSvg.classList.add('custom-svg'); imgEl.replaceWith(inlineSvg); })替换完成后,直接写CSS就能控制内部元素颜色:
.custom-svg .path-1 { fill: #1677ff; } .custom-svg .path-2 { stroke: #ff4d4f; }这个方案要求SVG资源和当前页面同源,或者SVG所在服务端配置了CORS跨域允许资源拉取;因为之前img已经加载过SVG,fetch请求一般会直接命中浏览器缓存,不会额外增加加载耗时。
动态生成DataURL替换src方案
如果不想做DOM替换,可以提前把SVG的内容存为字符串模板,需要改色的时候把模板里的色值替换成目标颜色,编码成DataURL之后直接赋值给img的src属性即可,不需要额外发网络请求。// 提前存好SVG模板,需要动态改的色值用占位符代替 const svgTpl = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="{{fillColor}}"><path d="M12 2l-10 20h20L12 2z"/></svg>`; const imgEl = document.querySelector('.custom-svg'); // 替换占位符为目标色,编码后赋值给src const coloredSvg = svgTpl.replace('{{fillColor}}', '#52c41a'); imgEl.src = `data:image/svg+xml;utf8,${encodeURIComponent(coloredSvg)}`;这个方案单色、多色SVG都支持,适合SVG资源不多、需要动态频繁换色的场景。
内容的提问来源于stack exchange,提问作者Gulbahar Jafar

