历史项目主题换肤升级指南
本文档提供将历史项目升级为支持主题换肤的完整操作指南,涵盖硬编码色值替换、旧 CSS 变量迁移、按钮色改造三大步骤。
目录
一、升级前准备
1.1 备份项目
# 创建备份分支
git checkout -b backup/theme-upgrade-$(date +%Y%m%d)
git push origin backup/theme-upgrade-$(date +%Y%m%d)
# 创建升级工作分支
git checkout -b feat/theme-upgrade1.2 确认需处理的文件范围
# 列出所有样式文件(.scss / .css / .less)
find src -type f \( -name "*.scss" -o -name "*.css" -o -name "*.less" \) | grep -v node_modules
# 列出所有 TSX / JSX 文件
find src -type f \( -name "*.tsx" -o -name "*.jsx" \) | grep -v node_modules1.3 排除项
以下文件类型 不纳入替换范围:
*.test.*、*.spec.*、__tests__/目录下的测试文件node_modules/目录- 已注释行
- 注释块中的内容
二、步骤一:硬编码色值替换
遍历当前项目源码,按以下规则将硬编码色值替换为 CSS 变量写法。
2.1 替换规则对照表
匹配总则(替换前必须遵守,优先级高于下方所有操作要求):
- 完全匹配优先:源码色值与下表列出的色值逐字符完全匹配(大小写不敏感)时 → 直接按对应规则替换。
- 近似匹配(仅以
#0564f5为基准,1-2 色阶差):源码色值虽未在表中列出,但与主品牌基准色#0564f5(rgb(5, 100, 245))差异极小(≤ 2 色阶)时 → 推断为主品牌色近似变体,替换为var(--brand-color)(含透明度时用var(--brand-color-rgb)),并在报告中标记[近似匹配]供人工复核。近似匹配只与#0564f5比较,不与表中其他色值比较;表中其余色值仅参与完全匹配。判定阈值:设Δ_ch = max(|ΔR|,|ΔG|,|ΔB|)、欧氏距离d,1 色阶差为Δ_ch ≤ 16 且 d ≤ 25,2 色阶差为Δ_ch ≤ 32 且 d ≤ 50,两者需同时满足。- 超阈值一律保留:与
#0564f5差异超出近似阈值(单通道 > 32 或欧氏距离 > 50)→ 保留原样,不替换。- 禁止基于色名自动扩展:不得基于色名、变量名(含
primary、blue)或上下文推断替换目标;替换必须由色值本身的匹配结果驱动。- 替换目标固定:本步骤所有命中色值仅替换为
var(--brand-color)/var(--brand-color-hover)(含-rgb伴侣变量),不做基于属性名的语义化变量推断(语义化变量用于新组件开发,见 如何支持主题换肤功能)。
主品牌色 → var(--brand-color)
| 硬编码色值 | 替换为 |
|---|---|
#0564f5 | var(--brand-color) |
#0564F5 | var(--brand-color) |
rgb(5, 100, 245) | var(--brand-color) |
rgb(5,100,245) | var(--brand-color) |
#096dd9 | var(--brand-color) |
#096DD9 | var(--brand-color) |
rgb(9, 109, 217) | var(--brand-color) |
rgb(9,109,217) | var(--brand-color) |
#2065cf | var(--brand-color) |
#2065CF | var(--brand-color) |
rgb(32, 101, 207) | var(--brand-color) |
rgb(32,101,207) | var(--brand-color) |
#1d77ff | var(--brand-color) |
#1D77FF | var(--brand-color) |
rgb(29, 119, 255) | var(--brand-color) |
rgb(29,119,255) | var(--brand-color) |
#1677ff / #1677FF(Ant Design v5 主色) | var(--brand-color) |
rgb(22, 119, 255) / rgb(22,119,255) | var(--brand-color) |
#0052d9 / #0052D9 | var(--brand-color) |
rgb(0, 82, 217) / rgb(0,82,217) | var(--brand-color) |
#2b7fff / #2B7FFF | var(--brand-color) |
rgb(43, 127, 255) / rgb(43,127,255) | var(--brand-color) |
#0060df / #0060DF | var(--brand-color) |
rgb(0, 96, 223) / rgb(0,96,223) | var(--brand-color) |
#1a7aff / #1A7AFF | var(--brand-color) |
rgb(26, 122, 255) / rgb(26,122,255) | var(--brand-color) |
次品牌色 → var(--brand-color-hover)
| 硬编码色值 | 替换为 |
|---|---|
#4e80f5 | var(--brand-color-hover) |
#4E80F5 | var(--brand-color-hover) |
rgb(78, 128, 245) | var(--brand-color-hover) |
rgb(78,128,245) | var(--brand-color-hover) |
#1890ff | var(--brand-color-hover) |
#1890FF | var(--brand-color-hover) |
rgb(24, 144, 255) | var(--brand-color-hover) |
rgb(24,144,255) | var(--brand-color-hover) |
#40a9ff | var(--brand-color-hover) |
#40A9FF | var(--brand-color-hover) |
rgb(64, 169, 255) | var(--brand-color-hover) |
rgb(64,169,255) | var(--brand-color-hover) |
#3886fb | var(--brand-color-hover) |
#3886FB | var(--brand-color-hover) |
rgb(56, 134, 251) | var(--brand-color-hover) |
rgb(56,134,251) | var(--brand-color-hover) |
#238dff | var(--brand-color-hover) |
#238DFF | var(--brand-color-hover) |
rgb(35, 141, 255) | var(--brand-color-hover) |
rgb(35,141,255) | var(--brand-color-hover) |
#3783ff | var(--brand-color-hover) |
#3783FF | var(--brand-color-hover) |
rgb(55, 131, 255) | var(--brand-color-hover) |
rgb(55,131,255) | var(--brand-color-hover) |
#4096ff / #4096FF(Ant Design v5 hover) | var(--brand-color-hover) |
rgb(64, 150, 255) / rgb(64,150,255) | var(--brand-color-hover) |
#5b8ff9 / #5B8FF9 | var(--brand-color-hover) |
rgb(91, 143, 249) / rgb(91,143,249) | var(--brand-color-hover) |
#69c0ff / #69C0FF | var(--brand-color-hover) |
rgb(105, 192, 255) / rgb(105,192,255) | var(--brand-color-hover) |
#4ca1dc / #4CA1DC | var(--brand-color-hover) |
rgb(76, 161, 220) / rgb(76,161,220) | var(--brand-color-hover) |
2.2 替换操作要求
要求 1:变量名保护
替换前需判断目标色值是否出现在类名/变量名中,若是则跳过。例如:
text-[#0564f5]→ 跳过(类名中含有色值)bg-[#0564f5]→ 跳过border-[#4e80f5]→ 跳过$blue-base: #096dd9→ 跳过(SASS 变量名含blue)@blue-6: #1890ff→ 跳过(Less 变量名含blue)
要求 2:注释保留原有写法
| 文件类型 | 处理方式 |
|---|---|
.scss / .less | 使用 // 单行注释保留原有写法 |
.css | 使用 /* */ 注释保留原有写法 |
示例(.scss 文件):
// ❌ 替换前
.button {
background-color: #0564f5;
}
// ✅ 替换后
.button {
// background-color: #0564f5; // [*] 已替换为 var(--brand-color)
background-color: var(--brand-color);
}示例(.css 文件):
/* ❌ 替换前 */
.button {
background-color: #0564f5;
}
/* ✅ 替换后 */
.button {
/* background-color: #0564f5; */ /* [*] 已替换为 var(--brand-color) */
background-color: var(--brand-color);
}要求 3:跳过测试文件和已注释行
*.test.*、*.spec.*及__tests__/目录下的文件直接跳过- 已被注释的行(
//或/* */)直接跳过
要求 4:以下场景跳过不替换
| 场景 | 说明 | 示例 |
|---|---|---|
| 在注释中 | 色值位于注释内容中 | // 背景色 #0564f5 → 跳过 |
| ECharts 属性 | 作为 echart 图表的属性值 | color: '#0564f5' 在 echart option 中 → 跳过 |
| 颜色数组中 | 色值位于数组字面量内 | ['#0564f5', '#4e80f5'] → 跳过 |
| var() 默认值 | 作为 var() 的回退值 | var(--custom-color, #0564f5) → 跳过 |
| class / 变量名含 blue | class 名或 SASS/Less 变量名包含 blue 关键字 | .text-blue-500 { color: #0564f5 } → 跳过$blue-base: #096dd9 → 跳过@blue-6: #1890ff → 跳过 |
| 取色器 / 调色板对象 | 色值作为对象属性值,且该对象所有属性值都是色值(hex / rgb / rgba)→ 认定为取色器对象,其中所有色值整体跳过 | { primary: '#0564f5', hover: '#4e80f5' } → 跳过 |
ECharts 场景最终方案:不替换 ECharts option 中的硬编码色值。ECharts 需要使用
getCssVarHex('--brand-color')将 CSS 变量转为 hex 值后传入,参阅 如何支持主题换肤功能。
取色器对象判定:同时满足「色值是对象字面量
{ ... }的属性值」「该对象每个属性值都是色值」「对象内无任何非色值属性(数字、布尔、文案、嵌套对象、函数、var()等)」三条时,才整体跳过。含非色值属性(如{ title: '主色', primary: '#0564f5' })则不算取色器,其中色值仍按常规规则判定。
blue 选择器向上回溯:
blue保护常是「选择器在上、色值在下」的多行/嵌套结构。对每个色值匹配行须先向上回溯其所属 CSS 规则块的选择器(SCSS/Less 嵌套需逐层向上拼接所有祖先选择器,含&.blue、&-blue等&拼接),拼接后任一 class 名含blue(大小写不敏感)→ 跳过。例:.card { .blue-tag { background: #4e80f5; } }中#4e80f5因祖先.blue-tag命中而跳过。
要求 5:rgba 色值使用 -rgb 伴侣变量替换
当硬编码色值为 rgba() 格式时,必须使用对应的 -rgb 伴侣变量并保留原有透明度:
rgba(5, 100, 245, 0.2) → rgba(var(--brand-color-rgb), 0.2)
rgba(78, 128, 245, 0.15) → rgba(var(--brand-color-hover-rgb), 0.15)核心原则:保留原始透明度,仅替换颜色分量部分。
注意:仅处理
rgba()格式,rgb()格式的色值按常规 hex 色值方式替换为var(--brand-color)等 hex 主变量。
8 位十六进制色值(含透明度)处理:源码中的 8 位色值 #RRGGBBAA 取前 6 位 #RRGGBB(大小写不敏感)与 2.1 表比对;命中则替换为 rgba(var(--xxx-rgb), <alpha>),其中 <alpha> = round(后 2 位 hex / 255, 2);未命中保留原样。
#0564f5ff → var(--brand-color) // AA=FF 完全不透明,直接用主变量
#0564f533 → rgba(var(--brand-color-rgb), 0.2) // 0x33/255 ≈ 0.2
#4e80f580 → rgba(var(--brand-color-hover-rgb), 0.5) // 0x80/255 ≈ 0.5
#123456ff → 保留原样 // 前 6 位未命中要求 6:先判定后替换,替换后执行遗漏检测
先判定后替换:每个色值匹配行在替换前,必须按固定顺序(不可打乱、不可跳步)跑完以下 6 项跳过检查,全部未命中才允许替换:
- 类名 / 变量名含色值(如
text-[#0564f5])→ 跳过 - 测试文件(
*.test.*、*.spec.*、__tests__/)→ 跳过 - 已注释行(以
//或/*开头、或被/* */包裹)→ 跳过 - blue 类选择器回溯(向上回溯所属规则块,任一层祖先选择器含
blue)→ 跳过 - ECharts 属性 / 颜色数组 /
var()回退值 / 取色器对象 → 跳过 - SASS / Less 变量名含
blue($blue-base、@blue-6)→ 跳过
块内已存在的
// var(...)注释仅跳过其自身(检查 3),不构成对同块其他活跃行的替换许可——每一行都独立走完上述 6 项检查。
替换后执行遗漏检测(必须,可自动重试):本步骤第一轮替换完成后,须重新全文搜索所有待替换色值(含 6 位 hex、8 位 hex、rgb、rgba 的各格式变形),对命中行逐一判断是否属于上述合法跳过场景;若存在既不属于合法跳过、又未被替换的色值 → 判定为遗漏,立即重新替换,再次检测,直到无遗漏方可进入下一步骤。
# 遗漏检测:搜索所有待替换的 6 位 hex 色值(排除已注释行、var() 回退值、测试文件、node_modules)
grep -rnE "#0564f5|#096dd9|#2065cf|#1d77ff|#1677ff|#0052d9|#2b7fff|#0060df|#1a7aff|#4e80f5|#1890ff|#40a9ff|#3886fb|#238dff|#3783ff|#4096ff|#5b8ff9|#69c0ff|#4ca1dc" \
--include="*.scss" --include="*.css" --include="*.less" \
--include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" \
--exclude-dir="__tests__" --exclude-dir="node_modules" -i \
| grep -v "^\s*//" | grep -v "^\s*/\*" | grep -v "var("要求 7:每次替换后检查代码逻辑
每次替换后,需确认改动不会破坏原有代码逻辑:
- 确认 CSS 变量名拼写正确
- 确认
var()语法正确 - 确认替换后颜色语义一致(主色 →
--brand-color,hover 色 →--brand-color-hover) - 若原代码依赖特定色值进行计算(如
darken()、lighten()等),调整为使用 CSS 变量或相应工具函数
要求 8:记录替换明细,汇入最终升级报告
本步骤替换过程中先临时记录改动明细(文件、原写法、替换后、匹配类型)。这些明细将在三大步骤全部完成后,依据当前项目代码的实际改动(git diff / git status)统一核对,汇总进项目根目录的 Neo主题换肤功能升级报告.md(一份报告覆盖硬编码替换、旧变量迁移、按钮改造三部分)。报告数据以实际 diff 为准,临时记录若与 diff 不符则以 diff 为准修正。
本步骤(硬编码色值替换)相关的报告片段格式如下:
# 硬编码色值 CSS 变量替换
## 汇总信息
| 指标 | 数值 |
|:--|:--|
| 扫描文件总数 | XXX |
| 修改文件总数 | XXX |
| 替换次数(主品牌色·完全匹配) | XXX |
| 替换次数(次品牌色·完全匹配) | XXX |
| 替换次数(近似匹配·1 色阶) | XXX |
| 替换次数(近似匹配·2 色阶) | XXX |
| 跳过次数 | XXX |
| 操作日期 | YYYY-MM-DD |
## 跳过详情
| 文件 | 行号 | 色值 | 跳过原因 |
|:--|:--|:--|:--|
| src/components/Foo.scss | 12 | #0564f5 | 变量名保护:类名含色值 text-[#0564f5] |
| src/components/Foo.scss | 78 | #3080d0 | 超阈值:与基准 #0564f5 差 Δ_ch=43,不视为品牌色 |
| ... | ... | ... | ... |
## 完全匹配替换详情
| 文件 | 原写法 | 替换后 | 状态 |
|:--|:--|:--|:--|
| src/components/Header.scss | `color: #0564f5` | `color: var(--brand-color)` | ✅ |
| src/components/Button.scss | `background: #4e80f5` | `background: var(--brand-color-hover)` | ✅ |
| ... | ... | ... | ... |
## 近似匹配详情(需人工复核)
> 匹配基准恒为 `#0564f5`,替换目标恒为 `var(--brand-color)`(含透明度时用 `var(--brand-color-rgb)`)。
| 文件 | 行号 | 源色值 | 匹配基准 | 色阶差 | Δ_ch | d | 替换为 |
|:--|:--|:--|:--|:--|:--|:--|:--|
| src/Foo.scss | 12 | `#0968f5` | `#0564f5` | 1 色阶 | 4 | 5.7 | `var(--brand-color)` |
| ... | ... | ... | ... | ... | ... | ... | ... |要求 9:不修改非相关内容
- 仅替换匹配硬编码色值列表中的值
- 不修改未在替换规则中列出的颜色值(如
#ff0000、#00ff00等) - 不修改代码结构、逻辑或其它样式属性
2.3 替换前后示例
SCSS 文件示例
// ========== 替换前 ==========
.nav-menu {
background-color: #0564f5;
&:hover {
background-color: #4e80f5;
}
}
.menu-item.active {
border-left: 3px solid #096dd9;
color: #1890ff;
}
.stat-card {
background: rgb(5, 100, 245);
}
// ========== 替换后 ==========
.nav-menu {
// background-color: #0564f5; // [*] 已替换为 var(--brand-color)
background-color: var(--brand-color);
&:hover {
// background-color: #4e80f5; // [*] 已替换为 var(--brand-color-hover)
background-color: var(--brand-color-hover);
}
}
.menu-item.active {
// border-left: 3px solid #096dd9; // [*] 已替换为 var(--brand-color)
border-left: 3px solid var(--brand-color);
// color: #1890ff; // [*] 已替换为 var(--brand-color-hover)
color: var(--brand-color-hover);
}
.stat-card {
// background: rgb(5, 100, 245); // [*] 已替换为 var(--brand-color)
background: var(--brand-color);
}CSS 文件示例
/* ========== 替换前 ========== */
.btn-primary {
background-color: #0564f5;
border-color: #4e80f5;
}
/* ========== 替换后 ========== */
.btn-primary {
/* background-color: #0564f5; */ /* [*] 已替换为 var(--brand-color) */
background-color: var(--brand-color);
/* border-color: #4e80f5; */ /* [*] 已替换为 var(--brand-color-hover) */
border-color: var(--brand-color-hover);
}TSX 文件示例
// ========== 替换前 ==========
const styles = {
headerBg: '#0564f5',
linkColor: '#4e80f5',
};
<div style={{ backgroundColor: '#0564f5', color: '#1890ff' }}>
// ========== 替换后 ==========
const styles = {
headerBg: 'var(--brand-color)',
linkColor: 'var(--brand-color-hover)',
};
<div style={{ backgroundColor: 'var(--brand-color)', color: 'var(--brand-color-hover)' }}>三、步骤二:旧 CSS 变量迁移
遍历所有样式文件,将旧的按钮色 CSS 变量替换为新的 CSS 变量写法。
说明:旧变量名带有
-bg后缀,新变量名去掉了-bg后缀且统一了命名规范。
3.1 新旧变量对照表
| 旧 CSS 变量(查找) | 新 CSS 变量(替换为) |
|---|---|
--color-button-filled-primary-bg | --color-button-filled-primary |
--color-button-filled-primary-bg-hover | --color-button-filled-primary-hover |
--color-button-filled-primary-bg-tint | --color-button-filled-primary-tint |
--color-button-filled-primary-bg-disabled | --color-button-filled-primary-disabled |
--color-button-filled-secondary-bg | --color-button-filled-primary-secondary |
--color-button-filled-secondary-bg-hover | --color-button-filled-primary-secondary-hover |
--color-button-filled-secondary-bg-disabled | --color-button-filled-primary-secondary-disabled |
3.2 操作方式
在项目源码中全文搜索旧变量名,逐项替换为新变量名:
# 搜索旧变量
grep -r "filled-primary-bg" src/
grep -r "filled-secondary-bg" src/
# 确认命中的文件和行号后,逐一替换3.3 替换前后示例
// ========== 替换前 ==========
.btn-primary {
background: var(--color-button-filled-primary-bg);
&:hover {
background: var(--color-button-filled-primary-bg-hover);
}
&:disabled {
background: var(--color-button-filled-primary-bg-disabled);
}
}
.btn-secondary {
background: var(--color-button-filled-secondary-bg);
&:hover {
background: var(--color-button-filled-secondary-bg-hover);
}
&:disabled {
background: var(--color-button-filled-secondary-bg-disabled);
}
}
// ========== 替换后 ==========
.btn-primary {
background: var(--color-button-filled-primary);
&:hover {
background: var(--color-button-filled-primary-hover);
}
&:disabled {
background: var(--color-button-filled-primary-disabled);
}
}
.btn-secondary {
background: var(--color-button-filled-primary-secondary);
&:hover {
background: var(--color-button-filled-primary-secondary-hover);
}
&:disabled {
background: var(--color-button-filled-primary-secondary-disabled);
}
}四、步骤三:按钮色改造
遍历所有样式文件,对 primary 模式按钮应用按钮色 CSS 变量。
重要:需要遍历完同一文件内的所有 primary 按钮样式块,不可遗漏。
4.1 使用规则 1:白色背景 primary 按钮
适用条件:class 含 button-primary / ant-btn-primary / btn-primary / a-Button--primary,且原有背景色为白色(#FFFFFF / #FFF / #ffffff / #fff)。
| 状态 | 操作 |
|---|---|
| 非 hover / active | color 和 border-color 改用 var(--color-button-filled-primary) |
| hover 态 | color 和 border-color 改用 var(--color-button-filled-primary-hover) |
| active 态 | color 和 border-color 改用 var(--color-button-filled-primary-active) |
// ========== 替换前:白色背景 primary 按钮 ==========
.btn-primary {
background: #fff;
color: #0564f5;
border-color: #0564f5;
&:hover {
background: #f0f7ff;
color: #4e80f5;
border-color: #4e80f5;
}
&:active {
color: #096dd9;
border-color: #096dd9;
}
}
// ========== 替换后 ==========
.btn-primary {
background: #fff;
color: var(--color-button-filled-primary);
border-color: var(--color-button-filled-primary);
&:hover {
background: #f0f7ff;
color: var(--color-button-filled-primary-hover);
border-color: var(--color-button-filled-primary-hover);
}
&:active {
color: var(--color-button-filled-primary-active);
border-color: var(--color-button-filled-primary-active);
}
}4.2 使用规则 2:非白色背景 primary 按钮
适用条件:class 含 button-primary / ant-btn-primary / btn-primary / a-Button--primary,且原有背景色不是白色。
| 状态 | 操作 |
|---|---|
| 非 hover / active | background 或 background-color 改用 var(--color-button-filled-primary);color 改用 var(--color-button-filled-primary-color) |
| hover 态 | background 或 background-color 改用 var(--color-button-filled-primary-hover);color 改用 var(--color-button-filled-primary-color-hover) |
| active 态 | background 或 background-color 改用 var(--color-button-filled-primary-active);color 改用 var(--color-button-filled-primary-color-hover) |
💡 为什么字体色
color必须使用按钮字体色变量?填充型 primary 按钮的文字直接叠在按钮背景色之上。如果
color使用固定色值(如#fff)或固定色值的 CSS 变量,一旦运行时把按钮背景色换成与该文字色相近的颜色,就会出现文字与背景色相近、看起来模糊的问题。
--color-button-filled-primary-color/--color-button-filled-primary-color-hover是随按钮背景色自动计算的对比色,能保证任意按钮色下文字都清晰可读。因此非白色背景 primary 按钮的color一律改用按钮字体色变量:
- 非 hover / active 态 →
var(--color-button-filled-primary-color)- hover / active 态 →
var(--color-button-filled-primary-color-hover)白色背景轮廓 primary 按钮的
color显示的是品牌色本身(文字即品牌色),仍使用--color-button-filled-primary系列,不改用按钮字体色变量。
// ========== 替换前:非白色背景 primary 按钮 ==========
.ant-btn-primary {
background-color: #0564f5;
color: #fff;
border: none;
&:hover {
background-color: #4e80f5;
}
&:active {
background-color: #096dd9;
}
}
// ========== 替换后 ==========
.ant-btn-primary {
background-color: var(--color-button-filled-primary);
color: var(--color-button-filled-primary-color);
border: none;
&:hover {
background-color: var(--color-button-filled-primary-hover);
color: var(--color-button-filled-primary-color-hover);
}
&:active {
background-color: var(--color-button-filled-primary-active);
}
}4.3 使用规则 3:所有 primary 模式按钮通用规则
遍历所有按钮类组件元素,找出 primary 模式的按钮,按以下规则实现:
| 条件 | 状态 | 操作 |
|---|---|---|
| 背景白色 | 非 hover / active | color + border-color → var(--color-button-filled-primary) |
| 背景白色 | hover 态 | color + border-color → var(--color-button-filled-primary-hover) |
| 背景白色 | active 态 | color + border-color → var(--color-button-filled-primary-active) |
| 背景非白色 | 非 hover / active | background-color → var(--color-button-filled-primary);color → var(--color-button-filled-primary-color) |
| 背景非白色 | hover 态 | background-color → var(--color-button-filled-primary-hover);color → var(--color-button-filled-primary-color-hover) |
| 背景非白色 | active 态 | background / background-color → var(--color-button-filled-primary-active);color → var(--color-button-filled-primary-color-hover) |
💡 字体色规则说明:非白色背景 primary 按钮的文字色
color必须使用按钮字体色变量(非 hover/active 态 →--color-button-filled-primary-color;hover/active 态 →--color-button-filled-primary-color-hover),而非固定色值或固定色值 CSS 变量,避免文字色与运行时切换后的按钮背景色相近导致文字模糊。
4.4 可用的按钮色 CSS 变量
| CSS 变量 | -rgb 伴侣变量(默认值) | 说明 |
|---|---|---|
--color-button-filled-primary | 5, 100, 245 | 填充主按钮 — 正常态背景色(★ 同时可用于 border/outline/text 颜色) |
--color-button-filled-primary-rgb | — | rgba() 半透明场景使用 |
--color-button-filled-primary-hover | 26, 122, 255 | 填充主按钮 — 鼠标悬停背景色 |
--color-button-filled-primary-hover-rgb | — | rgba() 半透明场景使用 |
--color-button-filled-primary-active | 0, 76, 207 | 填充主按钮 — 点击按下背景色 |
--color-button-filled-primary-active-rgb | — | rgba() 半透明场景使用 |
--color-button-filled-primary-tint | 230, 244, 255 | 填充主按钮 — 浅色背景 |
--color-button-filled-primary-tint-rgb | — | rgba() 半透明场景使用 |
--color-button-filled-primary-disabled | 128, 191, 255 | 填充主按钮 — 禁用态背景色 |
--color-button-filled-primary-disabled-rgb | — | rgba() 半透明场景使用 |
--color-button-filled-primary-color | — | 填充主按钮 — 正常态文字色(自动对比色) |
--color-button-filled-primary-color-hover | — | 填充主按钮 — 悬停文字色 |
--color-button-filled-primary-color-disabled | — | 填充主按钮 — 禁用文字色 |
--color-button-filled-primary-secondary | 26, 122, 255 | ★ 次按钮 — 正常态背景(降一级变浅,colors[4]) |
--color-button-filled-primary-secondary-rgb | — | rgba() 半透明场景使用 |
--color-button-filled-primary-secondary-hover | 5, 100, 245 | ★ 次按钮 — 悬停态背景(比 hover 降一级变浅) |
--color-button-filled-primary-secondary-hover-rgb | — | rgba() 半透明场景使用 |
--color-button-filled-primary-secondary-disabled | 168, 215, 255 | ★ 次按钮 — 禁用态背景(比 disabled 降一级变浅) |
--color-button-filled-primary-secondary-disabled-rgb | — | rgba() 半透明场景使用 |
4.5 按钮色改造前后示例
场景 A:白色背景的 primary 轮廓按钮
// ========== 改造前 ==========
.button-primary {
background-color: #fff;
color: #0564f5;
border: 1px solid #0564f5;
border-radius: 6px;
padding: 8px 20px;
cursor: pointer;
&:hover {
color: #4e80f5;
border-color: #4e80f5;
}
&:active {
color: #096dd9;
border-color: #096dd9;
}
&:disabled {
color: #80bfff;
border-color: #80bfff;
cursor: not-allowed;
}
}
// ========== 改造后 ==========
.button-primary {
background-color: #fff;
color: var(--color-button-filled-primary);
border: 1px solid var(--color-button-filled-primary);
border-radius: 6px;
padding: 8px 20px;
cursor: pointer;
&:hover {
color: var(--color-button-filled-primary-hover);
border-color: var(--color-button-filled-primary-hover);
background-color: rgba(var(--color-button-filled-primary-rgb), 0.06);
}
&:active {
color: var(--color-button-filled-primary-active);
border-color: var(--color-button-filled-primary-active);
}
&:disabled {
color: var(--color-button-filled-primary-disabled);
border-color: var(--color-button-filled-primary-disabled);
cursor: not-allowed;
}
}场景 B:非白色背景的填充 primary 按钮
// ========== 改造前 ==========
.ant-btn-primary {
background: #0564f5;
color: #fff;
border: none;
border-radius: 6px;
padding: 8px 24px;
font-weight: 500;
cursor: pointer;
&:hover {
background: #4e80f5;
}
&:active {
background: #096dd9;
}
&:disabled {
background: #80bfff;
cursor: not-allowed;
}
}
// ========== 改造后 ==========
.ant-btn-primary {
background: var(--color-button-filled-primary);
color: var(--color-button-filled-primary-color);
border: none;
border-radius: 6px;
padding: 8px 24px;
font-weight: 500;
cursor: pointer;
transition: background 0.3s ease;
&:hover {
background: var(--color-button-filled-primary-hover);
color: var(--color-button-filled-primary-color-hover);
}
&:active {
background: var(--color-button-filled-primary-active);
color: var(--color-button-filled-primary-color-hover);
}
&:disabled {
background: var(--color-button-filled-primary-disabled);
color: var(--color-button-filled-primary-color-disabled);
cursor: not-allowed;
}
}场景 C:次按钮
// ========== 改造前 ==========
.btn-secondary {
background: #a8d7ff;
color: #fff;
border: none;
border-radius: 6px;
padding: 6px 18px;
cursor: pointer;
&:hover {
background: #80bfff;
}
&:disabled {
background: #e6f4ff;
cursor: not-allowed;
}
}
// ========== 改造后 ==========
.btn-secondary {
background: var(--color-button-filled-primary-secondary);
color: var(--color-button-filled-primary-color);
border: none;
border-radius: 6px;
padding: 6px 18px;
cursor: pointer;
&:hover {
background: var(--color-button-filled-primary-secondary-hover);
}
&:disabled {
background: var(--color-button-filled-primary-secondary-disabled);
color: var(--color-button-filled-primary-color-disabled);
cursor: not-allowed;
}
}五、升级完成检查清单
完成以上三个步骤后,请逐项检查:
硬编码色值替换
- [ ] 匹配总则已遵守(完全匹配优先;1-2 色阶近似匹配仅以
#0564f5为基准并标记[近似匹配];超阈值一律保留;不基于色名扩展) - [ ] 所有匹配的硬编码色值已替换为
var(--brand-color)/var(--brand-color-hover)(含 6 位 hex、8 位 hex、rgb、rgba 格式) - [ ] 8 位 hex 色值(
#RRGGBBAA)已按前 6 位命中 + alpha 换算规则处理 - [ ] 类名/变量名中含色值的情况已正确跳过
- [ ] SCSS 文件中已用
//注释保留原有写法 - [ ] CSS 文件中已用
/* */注释保留原有写法 - [ ] 测试文件均已跳过
- [ ] ECharts option 中的色值未替换
- [ ] 颜色数组中的色值未替换
- [ ] 取色器 / 调色板对象(属性值全为色值)中的色值未替换
- [ ]
var()默认值中的色值未替换 - [ ] class 含
blue关键字、以及祖先选择器回溯后含blue的未替换 - [ ] 已执行遗漏检测,仅剩合法跳过项,无遗漏
- [ ] 改动明细已记录,待汇入最终
Neo主题换肤功能升级报告.md - [ ] 无破坏代码逻辑的变更
旧 CSS 变量迁移
- [ ]
--color-button-filled-primary-bg*→--color-button-filled-primary*全部替换 - [ ]
--color-button-filled-secondary-bg*→--color-button-filled-primary-secondary*全部替换
按钮色改造
- [ ] 白色背景 primary 按钮的
color+border-color已使用按钮色变量 - [ ] 非白色背景 primary 按钮的
background-color已使用按钮色变量 - [ ] 非白色背景 primary 按钮的字体色
color已改用按钮字体色变量(非 hover/active 态 →--color-button-filled-primary-color;hover/active 态 →--color-button-filled-primary-color-hover) - [ ] 每个文件内的所有 primary 按钮样式块均已遍历
- [ ] hover / active / disabled 各状态均有对应变量
- [ ] 次按钮已使用
--color-button-filled-primary-secondary*变量 - [ ]
ant-btn-primary的background-color已确认替换 - [ ] 已执行按钮改造遗漏检测,所有 primary 按钮的
background-color均为 CSS 变量或白色背景
最终验证
- [ ] 三大步骤全部完成后,已依据实际代码改动(
git diff/git status)生成Neo主题换肤功能升级报告.md - [ ] 报告内容与实际代码改动一致(改动文件数、替换次数、逐文件明细均与
git diff核对无误) - [ ] 项目构建无报错(
npm run build) - [ ] 切换不同主题后页面颜色正常响应
- [ ] 各按钮的 hover / active / disabled 状态交互正常
- [ ] ECharts 图表颜色显示正常
手动调试验证:在浏览器控制台执行以下命令,切换品牌色和按钮色确认效果:
// 切换品牌色(例:紫色)
NeoThemeHelper.setBaseColor("#923dda")
// 切换按钮色(例:橙色)
NeoThemeHelper.setButtonPrimaryColor("#ff6b35")提示:主题换肤在线 Demo 提供交互式控制面板,可直观预览各主题效果。
