什么是 CSS-in-JS?
CSS-in-JS 是一种将 CSS 样式直接写在 JavaScript 代码中的技术范式,它不是某个具体的库,而是一类解决方案的统称。传统开发中,CSS、JS、HTML 是分离的,而 CSS-in-JS 让样式成为 JS 的一部分,能利用 JS 的编程能力(如变量、条件判断、函数、模块化)来管理样式,最终通过运行时或编译时将 JS 中的样式转换成浏览器可识别的 CSS。
核心优势
- 作用域隔离:默认实现样式局部作用域,避免传统 CSS 的类名冲突(无需手动写 BEM 等命名规范)。
- 动态样式:能直接利用 JS 变量、状态(如 React 的 state)动态生成样式,比如根据用户主题、屏幕尺寸实时修改样式。
- 模块化:样式和组件紧密耦合,组件复用时样式也能一起复用,符合组件化开发思想。
- 无需额外编译配置:多数 CSS-in-JS 库无需单独配置 PostCSS、Less/Sass 等,开箱即用。
- 类型安全 :结合 TypeScript 时,能对样式属性做类型校验,避免拼写错误(如把
background写成backgroud)。 - 自动为 CSS 属性添加浏览器前缀(如 -webkit-),减少兼容性问题。
主流 CSS-in-JS 库
不同库的实现方式(运行时/编译时)、性能、API 略有差异,以下是最常用的几个:
| 库名 | 特点 | 适用场景 |
|---|---|---|
| styled-components | 最流行,API 优雅,支持样式继承、主题、自动前缀,纯运行时 | React 项目(个人/中小型) |
| emotion | 性能优于 styled-components,支持运行时/编译时,兼容 React/Vue 等 | 对性能有要求的 React 项目 |
| linaria | 编译时 CSS-in-JS,生成静态 CSS 文件,无运行时开销 | 大型项目、性能敏感场景 |
| styled-jsx | Next.js 内置,轻量,支持局部/全局样式 | Next.js 项目 |
实战范例 -- 以 styled-components 为例
先安装styled-components
bash
npm install styled-components
导入styled-components
js
import styled from 'styled-components';
基础使用
定义样式化组件(相当于创建带样式的 div)
js
const StyledContainer = styled.div`
transition: transform 0.3s ease-in-out;
&:hover {
transform: scale(1.05);
cursor: pointer;
}
`;
使用
html
<StyledContainer>
<h1>你好,React 19!</h1>
</StyledContainer>
效果如下

动态样式
js
import React, { useState } from 'react';
import styled from 'styled-components';
// 定义带动态属性的样式组件
const DynamicBox = styled.div`
width: 200px;
height: 200px;
background-color: ${props => props.bgColor}; // 接收 props 动态设置背景色
color: white;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s;
`;
function DynamicStyleDemo() {
// 定义状态
const [color, setColor] = useState('#1890ff');
return (
<div>
<DynamicBox bgColor={color}>当前颜色:{color}</DynamicBox>
{/* 点击按钮切换颜色 */}
<button onClick={() => setColor('#722ed1')} style={{ marginTop: 10 }}>
切换为紫色
</button>
<button onClick={() => setColor('#1890ff')} style={{ marginTop: 10, marginLeft: 10 }}>
切换为蓝色
</button>
</div>
);
}
export default DynamicStyleDemo;
样式继承
js
import styled from 'styled-components';
// 基础按钮样式
const BaseButton = styled.button`
padding: 8px 16px;
border: none;
border-radius: 4px;
cursor: pointer;
`;
// 继承基础按钮,扩展样式
const DangerButton = styled(BaseButton)`
background-color: #ff4d4f;
color: white;
&:hover {
background-color: #ff7875;
}
`;
// 使用
// <DangerButton>危险按钮</DangerButton>
全局样式
js
import { createGlobalStyle } from 'styled-components';
// 定义全局样式(相当于全局 CSS)
const GlobalStyle = createGlobalStyle`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
background-color: #f9f9f9;
}
`;
// 在根组件中引入
function App() {
return (
<>
<GlobalStyle />
{/* 其他组件 */}
</>
);
}
注意事项
- 性能问题:纯运行时的 CSS-in-JS(如 styled-components)会在浏览器运行时生成样式,首次渲染可能有轻微开销;大型项目建议选择编译时方案(如 linaria)。
- 调试:需安装对应调试工具(如 styled-components 的 Chrome 插件),否则无法在开发者工具中直接看到样式类名对应的源码。
- 服务端渲染(SSR):部分 CSS-in-JS 库(如 styled-components)需要额外配置才能在 SSR 中正常工作,否则会出现样式闪烁。
- 学习成本:需要适应"样式写在 JS 里"的思维,且不同库的 API 略有差异,需针对性学习。