canvas不解析css变量,必须用getcomputedstyle获取计算后的颜色字符串并.trim()后赋值给ctx.fillstyle,否则静默变黑;仅支持w3c标准色名、十六进制及逗号分隔的rgb()/rgba()格式。

Canvas 本身不解析 CSS,ctx.fillStyle = "var(--primary)" 会静默失效、图形变黑——这不是 bug,是设计如此。必须靠 JavaScript 桥接,把 CSS 变量“算出来”再喂给 Canvas。
为什么 getComputedStyle 是唯一可靠入口
Canvas 的 2D 上下文只认最终计算后的颜色字符串:"#3b82f6"、"rgb(59, 130, 246)"、"LightGreen"(注意大小写),它不访问样式表,也不执行 CSS 函数。所以不能读 element.style.setProperty(),也不能读未挂载元素的 :root 变量。
-
getComputedStyle(document.documentElement)适用于全局变量(如--accent),但必须等DOMContentLoaded或requestAnimationFrame第一帧之后调用 - 若变量定义在某个组件内部(如
<div id="chart" style="--bg: #1e293b">),就得传入该 <code>element,不能只读:root -
getComputedStyle(el).getPropertyValue('--theme-color')返回的是字符串,不是对象属性,写成el.style.--theme-color会语法错误 - 务必用
.trim(),否则' #3b82f6 '会被当成非法值,fallback 成黑色 - 变量未定义或语法错误时,
getPropertyValue()返回空字符串"",不是undefined,别用== null判断 - 建议兜底:
const color = cssVarToColor('--primary') || '#000' -
"rgba(255, 128, 0, 0.7)"✅ 兼容所有主流浏览器 Canvas 实现 -
"rgba(255 128 0 / 0.7)"❌ Safari 旧版、部分安卓 WebView 不支持 -
"hsl(200, 50%, 60%)"❌ Canvas 不解析 HSL 函数 -
"--primary-color"或"var(--primary)"❌ 静默转为黑色 -
"dark blue"❌ 空格分隔的颜色名不被识别("DarkBlue"才有效) - 监听
matchMedia('(prefers-color-scheme: dark)')可捕获系统主题变化 - 监听自定义事件或 MutationObserver 监控
:root样式表变更成本高,一般不推荐 - 最简单做法:在关键时机(如窗口聚焦、主题切换回调)重新调用
getComputedStyle并重绘 - 高频绘制场景(如
requestAnimationFrame)中,缓存读取结果,避免反复调用getComputedStyle
读取后必须 .trim() 和兜底
返回值总是字符串,但可能带前导/尾随空格、换行或无效语法(比如 " rgba(100, 200, 255, 0.8) ")。Canvas 对空格敏感,某些旧版 Safari 会直接忽略。
哪些颜色格式 Canvas 能直接用,哪些会静默失败
Canvas 支持 W3C 标准色名、十六进制、逗号分隔的 rgb()/rgba() 字符串;但对 HSL、空格分隔 rgba()、嵌套 var()、color-mix() 等完全不识别。
变量变更后 Canvas 不会自动重绘
CSS 变量更新(比如深色模式切换)不会触发 Canvas 重绘,必须手动监听 + 触发绘制逻辑。
真正容易被忽略的点不是怎么读,而是“什么时候读”和“读完怎么用”——DOM 必须已挂载、样式必须已计算、字符串必须已清洗、变更必须手动响应。漏掉任一环,颜色就对不上。











