CSS-in-JS 是用 JavaScript 函数或对象生成作用域隔离的 CSS 规则,非字符串拼接,而是通过库编译为带哈希的 class 名并注入 style 标签。
是的,但不是字符串拼接那种“写”。CSS-in-JS 是一种将样式逻辑与组件逻辑耦合的技术模式,核心是用 JavaScript 函数或对象生成可复用、作用域隔离的 CSS 规则。它不等于 element.style 内联样式,也不等于把 CSS 当字符串塞进 document.createElement('style')——而是通过库(如 styled-components、@emotion/react)把样式定义编译成真实 class 名,并注入 标签。
这是最典型的入门场景:需要根据 variant 或 disabled 动态切换样式。关键在于模板字符串里的插值语法和自动哈希类名机制。
import styled from 'styled-components';const Button = styled.button` padding: 8px 16px; border: none; border-radius: 4px; background-color: ${props => props.variant === 'primary' ? '#007bff' : '#6c757d'}; color: white; cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
&:hover:not(:disabled) { opacity: 0.9; } `;
// 使用
${...},且内部只能是函数(接收 props)或简单表达式;直接写字符串如 ${'red'} 会失效:disabled 这类状态需配合 props 判断,因为 DOM 状态不会自动同步到样式函数sc-bdVaJa kJjQqA,确保样式不污染全局两种主流写法,适用不同粒度:前者适合单个元素快速覆盖,后者适合提取
可复用样式对象。
/** 方式一:css prop(需开启 babel 插件 @emotion/babel-plugin) */
import { jsx } from '@emotion/react';
/** @jsxImportSource @emotion/react */
color: blue; font-weight: bold; @media (min-width: 768px) { font-size: 18px; } }
/>
/* 方式二:css 函数 + className /
import { css } from '@emotion/react';
const headingStyle = css margin: 0; line-height: 1.2; ;
标题
css 函数返回的是一个唯一 hash 字符串(如 css-1a2b3c),不是对象,不能直接当对象用css prop 写法更紧凑,但要求 JSX 编译支持;若用 TypeScript,需补充 declare module '@emotion/react' 声明props => ({ colors }) => css`color: ${colors.text};`
因为 CSS 属性名和 JS 对象键名规则冲突:比如 font-size 不能作属性名,background-image 需转为 backgroundImage;同时,纯对象无法表达嵌套(&)、伪类、媒体查询等 CSS 特性。
{ 'font-size': '14px' } 这种写法只适用于 Object.assign(element.style, ...),属于内联样式,不支持选择器、伪类、优先级控制useState + style 属性已足够;只有需要组件级封装、主题、响应式、条件样式时,才值得引入 CSS-in-JSCSS-in-JS 的真正门槛不在语法,而在理解「样式即函数」:它依赖运行时求值,意味着每次 props 变化都可能触发样式重新计算,过度嵌套插值或在 render 中创建新样式函数,容易引发性能问题。