css modules适合中大型项目中结构稳定、交互简单、复用率高的基础组件(如button、input),通过构建时生成哈希类名实现样式隔离与零运行时开销,需严格使用.module.css后缀及styles.xxx引用,不支持props动态插值。

CSS Modules 适合哪些场景
它解决的是“类名不冲突”和“样式只作用于当前组件”这两个最基础的问题,尤其适合中大型项目里那些结构稳定、交互简单、复用率高的 UI 元素——比如 Button、Input、Card。构建时生成哈希类名(如 Button_button__abc123),运行时零开销,打包体积几乎不增加。
常见错误是把 Button.css 当成 Button.module.css 用:import './Button.css' → 全局污染;必须写成 import styles from './Button.module.css',且类名只能通过 styles.button 访问。
- TypeScript 下不加
@types/css-modules或declare module '*.module.css',styles.xxx会报类型错误 - 无法直接在样式里读取
props,hover 或 active 状态得靠拼接 className:className={`${styles.base} ${isActive ? styles.active : ''}` - 不能用
@import引入非.module.css文件,否则破坏作用域隔离
Styled Components 的 runtime 成本在哪
它不是编译时注入 CSS,而是每次组件渲染都执行一次模板字符串解析 + 哈希生成 + 样式注入。这意味着:styled.button 不是静态组件定义,而是一个运行时函数调用。
典型卡点:组件频繁重渲染(比如受 useState 控制的动画按钮),${props => props.color} 这类插值表达式会被反复执行;服务端渲染若漏掉 ServerStyleSheet 或 Next.js 里没配 use client + createGlobalStyle,首屏就无样式或样式重复注入。
使用 @ainative/react-sdk 为 React 应用添加 AI 聊天和积分。适用于 (1) 安装 @ainative/react-sdk,(2) 使用 useChat hook 实现聊天完成。
- 打包体积多出约 14KB gzip(对比纯 CSS Modules)
- 浏览器 DevTools 里看到的是
sc-a1b2c3这类随机 class,调试时得切到 React DevTools 的 component tab 才能定位来源 -
createGlobalStyle必须确保全局只执行一次,重复调用会导致重置样式被多次插入
混用时怎么避免踩坑
真实项目基本都是混用,但边界要划清:基础布局、表单控件、图标等低交互组件用 CSS Modules;需要主题切换、状态机驱动、复杂过渡的组件(如 Tooltip、ThemeSwitcher)才上 Styled Components。
容易忽略的是两者依赖链不能交叉污染。比如 Button.module.css 里写了 @import 'reset.css',这个 reset.css 就会脱离模块作用域,变成全局样式;而 Styled Components 的全局重置(createGlobalStyle)如果被多个组件 import 并执行,就会重复注入。
- Next.js App Router 中,
createGlobalStyle必须放在use client组件内,且只挂载一次 - CSS Modules 文件里禁止
@import非.module.css资源 - Styled Components 的主题变量(
theme)必须由ThemeProvider提供,不能靠 props 一层层透传
选型关键不在“高级与否”,而在控制粒度
如果你的样式逻辑主要靠条件 class 切换(比如 isDisabled、size="large"),CSS Modules 更轻量、更可控;如果你的样式大量依赖运行时计算(比如颜色随数据变化、动画参数由 state 决定、媒体查询需响应 props),Styled Components 的插值能力就不可替代。
真正难决策的不是技术本身,而是团队对“样式归属”的共识:谁维护?改一个按钮边框,是前端工程师改 JS 文件,还是设计师改 CSS 文件?前者倾向 Styled Components,后者倾向 CSS Modules。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










