currentColor 是最稳的起点,适用于内联 SVG 且未硬编码 fill/stroke 的场景;外链 SVG、内部固定颜色或 use 引用未设继承均会导致失效。

直接用 currentColor 是最稳的起点
只要 SVG 是内联写法(即 <svg> 标签直接出现在 HTML 中),且没硬编码 fill 或 stroke 值,currentColor 就能立刻生效。它会自动继承父元素的 color CSS 属性,不需要 JS 干预。
常见失效点:
- <img src="icon.svg"> 这种外链方式完全不支持 currentColor,因为 SVG 被隔离在独立文档上下文
- SVG 内部写了 fill="#333" 或 fill="black",会覆盖父级 color
- 用了 <use href="#home"> 但没给包裹层加 fill: currentColor,或者源 <symbol> 自己带了固定颜色
推荐写法:<svg fill="currentColor"><path d="..."></svg>。比把 fill="currentColor" 写在 <path> 上更可靠——它会向下透传,除非子元素显式覆盖。
fill 和 stroke 的 JS 动态设置要避开 DOM 时机陷阱
用 querySelector 找 SVG 元素后直接改 setAttribute('fill', '#f00') 看似简单,但容易在元素未加载完成时执行失败。尤其当 SVG 来自异步加载、Vue/React 组件渲染或 <use> 引用时,DOM 节点可能还没就位。
稳妥做法:
- 对内联 SVG,确保脚本放在 </body> 前,或监听 DOMContentLoaded
- 对 <use> 引用的 SVG,得等 <symbol> 定义加载完毕,再查 <use> 渲染出的实际 <svg> 子树(注意 Shadow DOM 行为)
- 避免只改 <svg> 根节点的 fill,它不会自动影响内部 <path> —— 必须遍历子元素,或依赖 CSS 继承(如设 svg { fill: inherit })
用 feColorMatrix 滤镜做非简单色替换时得算清矩阵逻辑
当你需要“变灰”“反色”“提红”这类非单色映射效果,feColorMatrix 是唯一可控方案。但它不是调色盘,而是线性变换:每行控制一个输出通道(R/G/B/A),每列是输入通道权重加偏移。
立即学习“前端免费学习笔记(深入)”;
关键细节:
- 单位矩阵(全 0 和对角线 1)等于无变化;想保留红色只输出 R 通道,就得设第一行为 1 0 0 0 0,其余行全 0
- 最后一列是偏移量,单位是 [0, 1],比如 +0.2 相当于整体提亮 20%
- 浏览器对 <filter> 的缓存较弱,频繁切换滤镜可能触发重绘,不如纯 fill 切换轻量
- 不支持 IE10 以下,但现代项目基本可忽略
主题切换时别只靠 JS 改色,CSS 变量 + 类名更可持续
如果页面有深色/浅色模式,用 JS 遍历所有 SVG 并逐个改 fill 属性,后期维护成本高,也容易漏掉新加入的图标。
更优路径:
- 在 :root 定义 --icon-fill: #333,SVG 里用 fill="var(--icon-fill)"
- 切换主题时只切 body 类名,如 <body class="theme-dark">,再用 CSS 覆盖变量:.theme-dark { --icon-fill: #fff; }
- 对必须用 JS 控制的场景(比如根据背景亮度动态算色),优先封装成一个函数,统一处理所有固定定位 SVG,避免散落多处逻辑
最容易被忽略的是:当 SVG 同时用了 fill 属性和 style="fill: ..." 时,后者优先级更高,JS 改 setAttribute 无效,得用 element.style.fill = '...'。



















