DrillLab
第 75 / 105 道75 / 105 · #342

React 里怎么写样式

How to use styles in React

先自己答,再往下看Answer it yourself first

一句话:五种, 各有明确的取舍。

方式好处代价
普通 CSS / SCSS 文件零成本、能用全部 CSS 特性类名全局,会冲突
CSS Modules类名自动加哈希,天然隔离动态样式要配 CSS 变量
行内 style动态值最直接没有伪类、媒体查询、动画; 每次渲染新对象
CSS-in-JS(styled-components)能用 props 决定样式,作用域天然隔离运行时开销,SSR 要额外配置
原子化(Tailwind)不用起类名,产物体积可控JSX 里类名很长,团队要统一约定

「动态样式」的推荐做法—— 这是加分点:用 CSS 变量而不是行内 style。 把变量写在行内, 真正的样式规则还在 CSS 文件里 —— 这样既能动态,又保留伪类和媒体查询。本站的深色模式就是这么做的(切 data-theme 属性, CSS 变量整套换)。

会追问:「行内 style 为什么影响性能?」—— 每次渲染都创建新对象, 会破坏子组件的 memo; 而且它不能被浏览器按规则缓存。要用就 useMemo 稳住。

In one line: five ways, each with a clear trade-off.

ApproachUpsideCost
Plain CSS / SCSS filesFree, and every CSS feature is availableClass names are global, so they collide
CSS ModulesHashed class names, isolated by defaultDynamic styles need CSS variables
Inline styleThe most direct way to use a dynamic valueNo pseudo-classes, media queries or animations; a new object every render
CSS-in-JS (styled-components)props can drive the styles, and scoping needs no extra workRuntime cost, and SSR needs extra setup
Atomic (Tailwind)No naming, and the output size stays under controlVery long class strings in JSX, and the team needs conventions

The recommended way to do dynamic styles — this is the bonus point: use a CSS variable, not an inline style. Put only the variable inline and leave the actual rule in the CSS file — you get the dynamic value and keep pseudo-classes and media queries. That is how this site’s dark mode works (flip the data-theme attribute and the whole set of CSS variables swaps).

Follow-up: “Why do inline styles hurt performance?” — every render creates a new object, which breaks memo on the child, and the browser cannot cache it as a rule. If you must use one, stabilise it with useMemo.

JSX动态样式的正确做法示意Illustrative
1// 推荐:行内只放变量,规则留在 CSS 里
2<div className="bar" style={{ "--pct": `${percent}%` }} />
3
4/* CSS 里 */
5.bar::after { width: var(--pct); } /* 伪类照样能用 */
6@media (max-width: 480px) { .bar { height: 4px; } }
7
8// ✗ 行内写全套:没法写伪类和媒体查询,还每次新对象
9<div style={{ width: `${percent}%`, background: "#2b6" }} />
1// Recommended: only the variable goes inline, the rules stay in CSS
2<div className="bar" style={{ "--pct": `${percent}%` }} />
3
4/* In the CSS */
5.bar::after { width: var(--pct); } /* pseudo-classes still work */
6@media (max-width: 480px) { .bar { height: 4px; } }
7
8// ✗ everything inline: no pseudo-classes, no media queries, and a new object each time
9<div style={{ width: `${percent}%`, background: "#2b6" }} />