模板开发商最怕客户说“风格不变,颜色换成我们的品牌色”。如果颜色写死在几十个选择器里,改一次要半天,还容易漏。CSS 变量就是为这种场景准备的。
先分层,再定义变量
不要把变量直接命名成 red、blue。按用途分三层:品牌层、语义层、组件层。
:root {
/* 品牌层:只放原始色值 */
--brand-500: #2f6bff;
--brand-600: #1b4ce0;
--accent-400: #22d3ee;
/* 语义层:告诉浏览器这个颜色是干什么的 */
--color-primary: var(--brand-500);
--color-primary-hover: var(--brand-600);
--color-text: #1f2a3d;
--color-text-muted: #64748b;
--color-bg: #ffffff;
--color-surface: #f5f8fd;
--color-border: #e3e9f5;
/* 组件层:只被组件引用 */
--btn-radius: 12px;
--card-radius: 18px;
--shadow-card: 0 20px 40px -28px rgba(8, 20, 45, .45);
}
换肤时只改品牌层和少量语义层,组件层不用动。这样一套模板可以衍生出十几种风格,而 CSS 只有一份。
命名要稳定,别跟具体颜色绑定
用 primary、surface、muted 这类语义名,不要用 blue、gray。今天品牌色是蓝,明天可能换成绿,语义名不会过时。数字后缀只用于色阶,比如 500 是主色,600 是悬停,100 是浅底。
命名统一后,设计稿和代码能对上,交接成本会低很多。
深色模式不用复制整套 CSS
把所有语义变量在 [data-theme="dark"] 下重定义一遍即可,组件样式完全复用。
[data-theme="dark"] {
--color-text: #e8eefb;
--color-text-muted: #93a3bd;
--color-bg: #080f1e;
--color-surface: #0e1930;
--color-border: rgba(255,255,255,.10);
--shadow-card: 0 24px 50px -30px rgba(0,0,0,.85);
}
注意图片、图标、表单的边框也要跟着走,不要只改背景和文字。
给旧浏览器留回退
CSS 变量在现代浏览器支持很好,但如果客户还在用老旧内核,至少保证主色和文字色有回退值:
.btn {
background: #2f6bff;
background: var(--color-primary, #2f6bff);
}
回退值不要写太多,重点保证按钮、链接、正文这三处可读即可。
换肤时最容易漏的五个地方
- 表单的 focus 边框,很多模板写死了蓝色。
- SVG 图标里的 fill,内联 SVG 要改成 currentColor。
- 表格斑马纹,浅色底换深色后对比过强。
- 图片上的渐变遮罩,深色模式下会变得过重。
- 第三方组件,比如地图、客服、支付弹窗,颜色往往改不了,要提前和客户说明。
上线前把这五处逐一检查,基本不会出现“换了一半”的尴尬。
性能上的两个注意点
变量本身几乎不增加性能开销,但不要在 JS 里频繁读写大量 CSS 变量,那会触发样式重算。主题切换时一次性改根节点的 data 属性即可。
另外,不要把上百个变量全部塞进 :root。只暴露真正需要换的,其余留在组件内部,CSS 会更容易维护。
相关阅读:模板交付前检查清单。
常见问题
CSS 变量能用在媒体查询里吗?
不能直接用在媒体查询的条件中,但可以在媒体查询里重新赋值,这是常规做法。
换肤需要重新打包吗?
如果只是改变量值,不需要。把主题变量单独放一个文件,切换时加载对应文件即可。
老客户已有定制样式怎么办?
先抽变量,再把定制样式收敛到变量覆盖层,不要直接改组件 CSS。这样后续升级模板不会冲突。
变量体系搭好后,模板的二次开发会轻松很多,规范可以对照模板二次开发规范。