CSS自定义属性在打印样式中不会重新计算,而是首次渲染时快照式求值;必须在@media print {:root{}}中显式重定义所有需切换的变量,否则沿用屏幕端值。

CSS自定义属性在打印样式中不是“表现不一致”,而是根本没被重新计算——浏览器只在初始渲染时求值一次 var(),@media print 里改 :root 变量,对已解析的样式毫无影响。
为什么 var(--color) 在打印预览里还是屏幕色
你写了 :root { --text-color: #007bff; },又在 @media print { :root { --text-color: #000; } } 里重赋值,但打印出来仍是蓝色。这不是规则没加载,是浏览器早在页面首次渲染时就把所有 color: var(--text-color) 展开成了 color: #007bff,之后无论 :root 怎么变,它都不再回溯更新。
这符合 CSS 自定义属性规范,不是 bug,是设计使然:var() 是“快照”,不是“引用”。
- 必须在
@media print中对每个被实际使用的变量显式重定义,漏一个,就沿用屏幕端值 - 常见必重定义变量:
--text-color、--border-color、--bg-color、--spacing-unit、--print-hidden - 别往
@media print里塞--hover-bg这类交互变量——它们压根不会被读取
@media print { :root { ... } } 写法极易失效
以下写法全部无效:
立即学习“前端免费学习笔记(深入)”;
-
@media print { html { --text-color: #000; } }——html不是继承根,变量不会透传到后代 -
@media print { .report { --text-color: #000; } }—— 打印时该元素可能不在.report选择器匹配路径下(比如被包裹在#app里且未透传) -
--text-color: #000 !important——!important不能用于自定义属性声明,语法错误
唯一正确写法:@media print { :root { --text-color: #000; } }。所有需切换的变量必须统一声明在 :root,且必须在 @media print 块内重置。
调试时最常忽略的验证方式和缓存陷阱
Chrome 打印预览会缓存旧的 CSS 规则。哪怕你刚改了 @media print { :root { --text-color: #000; } },DevTools 的 Styles 面板在普通视图下显示的仍是屏幕端结果。
真实生效值只能这样验证:
- 打开打印预览(
Ctrl+P或Cmd+P) - 右键目标元素 → “检查”
- 在 Elements 面板中选中该元素,看右侧 Styles 面板里
var(--text-color)最终计算出的值 - 如果仍显示
#007bff,说明:root在@media print中没生效,或被其他规则覆盖
强制关闭再打开打印预览,比热更新更可靠;别信“看起来应该变了”,只信 computed 值。
变量单位与降级问题常被当成“颜色不一致”
打印引擎不处理 alpha 通道,rgba(0, 0, 0, 0.8) 会被丢弃或降为灰度;var(--text-primary) 若未在 @media print 中静态重定义,会 fallback 到 initial(通常是黑色或透明)。
- 所有
rgba()必须手动替换为rgb()或十六进制,例如:rgba(231, 76, 60, 0.9) → #e74c3c - Sass/Less 中的
fade-out()、transparentize()等函数会悄悄输出rgba(),需在 print 媒体查询中覆盖 - 检查变量使用点:若
--text-primary在@media print外定义,必须在 print 块内重赋值,如:root { --text-primary: #000; }
真正容易被忽略的是:变量重定义必须覆盖所有被引用路径,且必须在打印上下文真正激活前完成——它不响应 JS 动态修改,也不随 DOM 变化延迟更新。



















