styled-jsx是Next.js原生支持的CSS-in-JS方案,开箱即用、默认局部作用域、零运行时开销,无需安装或配置;它天然支持SSR/静态生成,构建时提取样式,避免hydration mismatch。

styled-jsx 默认支持局部样式,无需额外配置
Next.js 从 13.0 开始默认内置 styled-jsx,不需要 npm install 或修改 next.config.js。它天然作用域隔离,写在组件内的 只影响当前组件,不会泄露到全局或干扰其他组件。
常见错误是手动安装 styled-jsx 并试图用 Babel 插件重载——这反而可能破坏 Next.js 的服务端渲染(SSR)样式注入逻辑,导致首屏无样式或重复插入 标签。
- 确保没在
package.json中显式添加styled-jsx依赖(Next.js 已打包进next包内) - 不要在
.babelrc或next.config.js中配置styled-jsx/babel - JSX 中的
必须是直接子节点,不能包裹在 Fragment、条件语句或变量中
正确写法:在函数组件内部使用
styled-jsx 的样式必须写在组件的 JSX 返回体内部(或紧邻返回语句),且需用 jsx 属性声明。它会自动编译为带唯一哈希类名的 CSS,并注入到 中(SSR 时)或运行时(CSR 时)。
下面是一个典型可用示例:
export default function Button() {
return (
<button classname="my-button">
Click me
<style jsx>{`
.my-button {
background: #0070f3;
color: white;
border-radius: 4px;
padding: 8px 16px;
}
.my-button:hover {
opacity: 0.8;
}
`}</style></button>
);
}
- 类名(如
.my-button)只在该组件内生效,即使其他组件也用.my-button,也不会冲突 - 不支持嵌套语法(如
&:hover),必须写全选择器 - 动态样式需用插值(
{variable}),但变量必须是字符串,不能是对象
如何在服务端渲染中避免样式重复或缺失
Next.js 在 SSR 时会提取 内容并注入到 HTML 的 ;客户端 Hydration 时复用同一份样式。但如果组件被多次渲染(比如列表中多个相同组件),styled-jsx 会自动去重——前提是类名和样式内容完全一致。
容易出问题的点:
- 用
Math.random()或时间戳生成动态类名 → 破坏哈希一致性 → 多次插入样式 → 重复标签 - 服务端与客户端计算出的哈希不一致(罕见,通常因环境变量或未序列化的闭包导致)→ 首屏样式错乱
- 在
useEffect中动态插入→ 客户端才生效,SSR 无样式
解决办法:所有样式逻辑保持纯函数、可序列化;避免在 useEffect 或事件回调里操作 。
需要全局样式或 CSS-in-JS 增强功能怎么办
styled-jsx 是轻量级局部方案,不支持主题、媒体查询嵌套、CSS 变量注入等高级能力。如果项目需要这些,别硬改 styled-jsx,而是按场景切换方案:
- 全局基础样式(重置、字体、变量):用
app/globals.css(App Router)或pages/_app.js中引入global.css - 带主题/变体的组件:改用
styled-components或emotion,但需配ssr: true和cache实例以保 SSR 正确性 - 需要关键 CSS 提取或 PostCSS 功能:放弃
styled-jsx,改用css-modules(Button.module.css)或tailwind
强行给 styled-jsx 加 PostCSS 插件或主题上下文,只会让构建变慢、调试变难,且失去 Next.js 内置优化。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











