原生 CSS 变量需用:root 或选择器声明 –xxx,仅支持 var()引用,不支持计算、条件或函数内嵌;PostCSS 靠插件如 postcss-mixins 模拟 mixin 但无参数校验;CSS-in-JS 适用于运行时动态逻辑。

CSS 原生变量怎么声明和使用
原生 CSS 变量(:root 或选择器内 --xxx)能复用值,但不是“运行时变量”——它不支持计算、条件、拼接或函数调用。
常见错误是写成 --size: 1rem * 2 或 color: var(--primary) + #222,这会直接失效,浏览器忽略整条声明。
- 必须用
:root或具体选择器声明,如:root {--color-primary: #007bff;} - 引用时只能用
var(--color-primary),不能嵌套在其他函数里(calc(var(--size) * 2)✅,但rgba(var(--rgb), 0.5)❌,因为--rgb若是255, 0, 0字符串,rgba()不接受) - 兼容性:IE 完全不支持;Android 4.4–6.0 的 WebView 有部分 bug,比如动态修改后不重绘
PostCSS 能否实现类似 Sass 的混合宏
PostCSS 本身不提供混合宏(@mixin),但靠插件可以逼近效果——关键是选对插件,且别指望它完全等价于 Sass。
最常用的是 postcss-mixins,但它只做静态替换,不支持参数校验、作用域隔离或嵌套上下文。
立即学习 “ 前端免费学习笔记(深入)”;
- 写法示例:
@define-mixin center {display: flex; justify-content: center; align-items: center;},然后用@mixin center调用 - 不支持动态参数类型判断(比如无法区分传入的是长度还是颜色),所有参数都是字符串原样插入
- 如果混用
postcss-custom-properties和postcss-mixins,注意执行顺序:变量插件必须在 mixin 插件之后,否则var(--x)在 mixin 展开前未被识别
为什么用 CSS-in-JS 替代传统预处理器
当组件级作用域、运行时主题切换、响应式值依赖 props 或 hooks 时,纯 CSS 工具链会卡住——变量和混合宏解决不了动态逻辑。
比如想根据 props.size 自动算出 padding 和 font-size,或者点击后切换深色模式并实时更新所有组件的 --bg,这时 styled-components 或 Emotion 的插值能力就不可替代。
-
styled.div`padding: ${p => p.size === 'lg' ? '1.5rem' : '0.75rem'};`—— 这种推导 CSS 值的方式,原生 CSS 和 PostCSS 都做不到 - 注意:服务端渲染(SSR)时,若主题依赖客户端状态(如 prefers-color-scheme),首次 HTML 中的变量可能错位,得靠
useEffect补正或用darkMode类名兜底 - 打包体积增加约 8–12KB(gzip 后),对超轻量站点要权衡
构建流程中变量与宏的实际取舍点
真正决定用哪套方案的,往往不是“哪个更酷”,而是“谁先出问题、谁最难调试”。
比如设计系统交付给多个前端团队,用 Sass 写了一堆 @mixin button-variant($type),但某团队在 Web Component 中用 Shadow DOM,Sass 编译后的类名无法穿透样式边界——这时候强行塞变量或宏反而增加维护成本。
- 优先用原生
--xxx变量:适合全局主题色、间距标尺、断点阈值等静态配置 - 需要逻辑分支或循环生成规则?别硬套 PostCSS 插件,直接上 JS 工具函数生成 CSS 字符串(如用
csstype+ 模板字面量) - 混合宏若只用于内部项目且无 SSR/ 跨框架需求,
postcss-mixins足够;一旦涉及微前端或 Design Token 同步,就得切到 JSON Schema + CLI 工具生成多格式输出
变量和宏的边界其实很薄——真正难的不是怎么写,而是当一个按钮同时要响应主题、尺寸、状态、密度四个维度时,如何让生成的 CSS 既可读、又可 debug、还不重复爆炸。这时候,工具只是辅助,结构设计才是关键。