CSS-in-JS 是运行时生成样式并注入 标签的模式,核心是样式与组件逻辑共存、可动态计算、天然作用域隔离;如 styled-components 通过插值函数响应 props,生成唯一 class 并复用规则。

什么是 CSS-in-JS?它不是把 CSS 写进 JS 字符串里那么简单
CSS-in-JS 是一种**运行时生成样式并注入 标签**的模式,核心在于:样式逻辑与组件逻辑共存、可基于 props 或状态动态计算、天然支持作用域隔离。它 ≠ element.style.color = 'red',也不等于用 JS 拼接字符串塞进 innerHTML。
真正有效的 CSS-in-JS 方案(如 styled-components、emotion、linaria)会在首次渲染时将样式规则转为唯一 class 名,写入文档头部的 标签,并复用已生成的规则避免重复插入。
如何用 styled-components 动态控制样式?关键在插值函数和属性透传
动态样式的本质是让 CSS 规则能响应 JS 变量。在 styled-components 中,这通过模板字符串内的插值函数实现,且组件 props 会自动透传给该函数。
import styled from 'styled-components';const Button = styled.button` background-color: ${props => props.primary ? '#007bff' : '#6c757d'}; color: white; border: none; padding: 8px 16px; border-radius: 4px;
&:hover { opacity: ${props => props.disabled ? 1 : 0.8}; }
/ 注意:这里不能直接写 props.size,必须映射成 CSS 值 / font-size: ${props => props.size === 'large' ? '18px' : '14px'}; `;
- 插值函数返回的必须是合法 CSS 值(带单位),不能是布尔或数字(除非你显式转换)
- 不要在插值中调用复杂逻辑或副作用函数,它只应做映射
-
disabled这类原生属性会被自动加到 DOM 元素上,但不会自动影响样式——得靠你在样式里显式判断
不用第三方库,纯 JS 动态管理样式有哪些可靠方式?
如果项目不能引入 styled-components 或 emotion,仍有几种可控方案:
立即学习“Java免费学习笔记(深入)”;
- 用
CSSStyleSheet.insertRule()手动插入带唯一标识的规则,再通过 class 控制元素 —— 适合全局少量动态主题 - 用
element.classList.toggle('active')配合预设 CSS 类 —— 最轻量,推荐用于开关类交互(如展开/收起) - 避免直接操作
element.style.xxx,除非是动画过渡中的临时内联样式;否则容易覆盖 CSS 文件定义的优先级,且无法利用浏览器样式缓存 - 若需根据数据生成大量样式(如图表颜色映射),建议生成
标签一次性注入,而不是为每个元素设style
为什么 createGlobalStyle 和 css 辅助函数容易被误用?
createGlobalStyle(来自 styled-components)和 css 函数常被当成“写普通 CSS 的捷径”,但它们的行为有隐含约束:
-
createGlobalStyle插入的样式是全局生效的,且**同一组件多次渲染不会去重**——如果它被用在条件渲染分支里,可能重复注入相同规则 -
css返回的是一个样式对象(非字符串),只能用在styled.xxx或css嵌套中,不能直接赋给style属性 - 两者都依赖
styled-components的底层样式注册机制,脱离其 Provider 或 SSR 环境时行为不可靠
真正需要全局样式时,更稳妥的做法仍是维护一个独立的 global.css,或用 insertRule + 标识符检查来手动管理。
动态样式的难点不在“怎么改”,而在于“改了之后是否可预测、可回退、不泄漏”。每次新增一个基于 props 的样式分支,都要问一句:这个 class 名会不会重复?这条规则有没有被其他组件意外覆盖?服务端渲染时它是否稳定生成?










