11---
2- source-updated-at : ' 2025-05-16T04:52:11 .000Z'
3- translation-updated-at : ' 2025-05-17T02:11:04.312Z '
2+ source-updated-at : 2025-05-19T22:31:51 .000Z
3+ translation-updated-at : 2025-05-19T23:06:25.929Z
44title : 如何在应用中使用 CSS
55nav_title : CSS
66description : 了解在应用中添加 CSS 的不同方式,包括 CSS 模块 (CSS Modules)、全局 CSS (Global CSS)、Tailwind CSS 等。
77related :
8- title : 后续步骤
9- description : 进一步了解在应用中使用 CSS 的其他方法 。
8+ title : 下一步
9+ description : 进一步了解在应用中使用 CSS 的其他方式 。
1010 links :
1111 - app/guides/tailwind-css
1212 - app/guides/sass
@@ -24,9 +24,11 @@ Next.js 提供了多种在应用中使用 CSS 的方式,包括:
2424
2525## CSS 模块 (CSS Modules)
2626
27- CSS 模块 (CSS Modules) 通过生成唯一的类名来实现 CSS 的局部作用域。这允许你在不同文件中使用相同的类名,而不用担心命名冲突 。
27+ CSS 模块 (CSS Modules) 通过生成唯一的类名来实现 CSS 的局部作用域。这允许你在不同文件中使用相同的类名而无需担心命名冲突 。
2828
29- 要开始使用 CSS 模块,创建一个扩展名为 ` .module.css ` 的新文件,并将其导入到 ` app ` 目录中的任何组件:
29+ <AppOnly >
30+
31+ 要开始使用 CSS 模块 (CSS Modules),创建一个扩展名为 ` .module.css ` 的文件,并将其导入到 ` app ` 目录下的任意组件中:
3032
3133``` css filename="app/blog/styles.module.css"
3234.blog {
@@ -35,26 +37,58 @@ CSS 模块 (CSS Modules) 通过生成唯一的类名来实现 CSS 的局部作
3537```
3638
3739``` tsx filename="app/blog/page.tsx" switcher
38- import styles from ' ./styles .module.css'
40+ import styles from ' ./blog .module.css'
3941
40- export default function Page({ children } : { children : React . ReactNode } ) {
41- return <main className = { styles .blog } >{ children } </main >
42+ export default function Page() {
43+ return <main className = { styles .blog } ></main >
4244}
4345```
4446
4547``` jsx filename="app/blog/page.js" switcher
46- import styles from ' ./styles.module.css'
48+ import styles from ' ./blog.module.css'
49+
50+ export default function Layout () {
51+ return < main className= {styles .blog }>< / main>
52+ }
53+ ```
54+
55+ </AppOnly >
4756
48- export default function Page ({ children }) {
49- return < main className= {styles .blog }> {children}< / main>
57+ <PagesOnly >
58+
59+ 要开始使用 CSS 模块 (CSS Modules),创建一个扩展名为 ` .module.css ` 的文件,并将其导入到 ` pages ` 目录下的任意组件中:
60+
61+ ``` css filename="/styles/blog.module.css"
62+ .blog {
63+ padding : 24px ;
5064}
5165```
5266
67+ ``` tsx filename="pages/blog/index.tsx" switcher
68+ import styles from ' ./blog.module.css'
69+
70+ export default function Page() {
71+ return <main className = { styles .blog } ></main >
72+ }
73+ ```
74+
75+ ``` jsx filename="pages/blog/index.js" switcher
76+ import styles from ' ./blog.module.css'
77+
78+ export default function Page () {
79+ return < main className= {styles .blog }>< / main>
80+ }
81+ ```
82+
83+ </PagesOnly >
84+
5385## 全局 CSS (Global CSS)
5486
55- 你可以使用全局 CSS 来在整个应用中应用样式。
87+ 你可以使用全局 CSS (Global CSS) 在整个应用中应用样式。
88+
89+ <AppOnly >
5690
57- 要使用全局样式, 创建一个 ` app/global.css ` 文件,并在根布局中导入它,以将样式应用到应用中的** 每个路由** :
91+ 创建一个 ` app/global.css ` 文件,并在根布局中导入它,以将样式应用到应用中的** 每个路由** :
5892
5993``` css filename="app/global.css"
6094body {
6599```
66100
67101``` tsx filename="app/layout.tsx" switcher
68- // 这些样式将应用到应用中的每个路由
102+ // 这些样式会应用到应用中的每个路由
69103import ' ./global.css'
70104
71105export default function RootLayout({
@@ -82,7 +116,7 @@ export default function RootLayout({
82116```
83117
84118``` jsx filename="app/layout.js" switcher
85- // 这些样式将应用到应用中的每个路由
119+ // 这些样式会应用到应用中的每个路由
86120import ' ./global.css'
87121
88122export default function RootLayout ({ children }) {
@@ -94,11 +128,31 @@ export default function RootLayout({ children }) {
94128}
95129```
96130
97- > ** 须知:** 全局样式可以导入到 ` app ` 目录中的任何布局、页面或组件 。但由于 Next.js 使用 React 内置的样式表支持来与 Suspense 集成,目前这不会在路由之间导航时移除样式表,可能会导致冲突 。我们建议将全局样式用于** 真正** 全局的 CSS,而使用 [ CSS 模块 (CSS Modules)] ( #css-modules ) 来处理局部作用域的 CSS。
131+ > ** 须知:** 全局样式可以导入到 ` app ` 目录下的任何布局、页面或组件中 。但由于 Next.js 使用 React 内置的样式表支持来与 Suspense 集成,目前这不会在路由切换时移除样式表,可能导致冲突 。我们建议将全局样式用于** 真正** 全局的 CSS,而使用 [ CSS 模块 (CSS Modules)] ( #css-modules ) 来限定 CSS 作用域 。
98132
99- ## 外部样式表 (External Stylesheets)
133+ </ AppOnly >
100134
101- 由外部包发布的样式表可以导入到 ` app ` 目录中的任何位置,包括并置的组件:
135+ <PagesOnly >
136+
137+ 在 ` pages/_app.js ` 文件中导入样式表,以将样式应用到应用中的** 每个路由** :
138+
139+ ``` tsx filename="pages/_app.js"
140+ import ' @/styles/global.css'
141+
142+ export default function MyApp({ Component , pageProps }) {
143+ return <Component { ... pageProps } />
144+ }
145+ ```
146+
147+ 由于样式表的全局性质,为避免冲突,你应该在 [ ` pages/_app.js ` ] ( /docs/pages/building-your-application/routing/custom-app ) 中导入它们。
148+
149+ </PagesOnly >
150+
151+ ## 外部样式表 (External stylesheets)
152+
153+ <AppOnly >
154+
155+ 外部包发布的样式表可以导入到 ` app ` 目录中的任何位置,包括同目录的组件:
102156
103157``` tsx filename="app/layout.tsx" switcher
104158import ' bootstrap/dist/css/bootstrap.css'
@@ -128,4 +182,113 @@ export default function RootLayout({ children }) {
128182}
129183```
130184
131- 外部样式表必须直接从 npm 包导入,或下载并与你的代码库并置。不能使用 ` <link rel="stylesheet" /> ` 。
185+ > ** 须知:** 在 React 19 中,也可以使用 ` <link rel="stylesheet" href="..." /> ` 。更多信息请参阅 [ React ` link ` 文档] ( https://react.dev/reference/react-dom/components/link ) 。
186+
187+ </AppOnly >
188+
189+ <PagesOnly >
190+
191+ Next.js 允许你从 JavaScript 文件中导入 CSS 文件。这是因为 Next.js 扩展了 [ ` import ` ] ( https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import ) 的概念,使其不仅限于 JavaScript。
192+
193+ ### 从 ` node_modules ` 导入样式
194+
195+ 自 Next.js ** 9.5.4** 起,允许从 ` node_modules ` 导入 CSS 文件到应用中的任何位置。
196+
197+ 对于全局样式表,如 ` bootstrap ` 或 ` nprogress ` ,你应该在 ` pages/_app.js ` 中导入文件。例如:
198+
199+ ``` jsx filename="pages/_app.js"
200+ import ' bootstrap/dist/css/bootstrap.css'
201+
202+ export default function MyApp ({ Component, pageProps }) {
203+ return < Component {... pageProps} / >
204+ }
205+ ```
206+
207+ 对于第三方组件所需的 CSS,你可以在组件中导入。例如:
208+
209+ ``` jsx filename="components/example-dialog.js"
210+ import { useState } from ' react'
211+ import { Dialog } from ' @reach/dialog'
212+ import VisuallyHidden from ' @reach/visually-hidden'
213+ import ' @reach/dialog/styles.css'
214+
215+ function ExampleDialog (props ) {
216+ const [showDialog , setShowDialog ] = useState (false )
217+ const open = () => setShowDialog (true )
218+ const close = () => setShowDialog (false )
219+
220+ return (
221+ < div>
222+ < button onClick= {open}> Open Dialog< / button>
223+ < Dialog isOpen= {showDialog} onDismiss= {close}>
224+ < button className= " close-button" onClick= {close}>
225+ < VisuallyHidden> Close< / VisuallyHidden>
226+ < span aria- hidden> ×< / span>
227+ < / button>
228+ < p> Hello there . I am a dialog< / p>
229+ < / Dialog>
230+ < / div>
231+ )
232+ }
233+ ```
234+
235+ </PagesOnly >
236+
237+ ## 排序与合并 (Ordering and Merging)
238+
239+ Next.js 在生产构建时会通过自动分块(合并)样式表来优化 CSS。** CSS 的顺序** 取决于** 你在代码中导入样式的顺序** 。
240+
241+ 例如,` base-button.module.css ` 会排在 ` page.module.css ` 之前,因为 ` <BaseButton> ` 在 ` page.module.css ` 之前导入:
242+
243+ ``` tsx filename="page.ts" switcher
244+ import { BaseButton } from ' ./base-button'
245+ import styles from ' ./page.module.css'
246+
247+ export default function Page() {
248+ return <BaseButton className = { styles .primary } />
249+ }
250+ ```
251+
252+ ``` jsx filename="page.js" switcher
253+ import { BaseButton } from ' ./base-button'
254+ import styles from ' ./page.module.css'
255+
256+ export default function Page () {
257+ return < BaseButton className= {styles .primary } / >
258+ }
259+ ```
260+
261+ ``` tsx filename="base-button.tsx" switcher
262+ import styles from ' ./base-button.module.css'
263+
264+ export function BaseButton() {
265+ return <button className = { styles .primary } />
266+ }
267+ ```
268+
269+ ``` jsx filename="base-button.js" switcher
270+ import styles from ' ./base-button.module.css'
271+
272+ export function BaseButton () {
273+ return < button className= {styles .primary } / >
274+ }
275+ ```
276+
277+ ### 推荐做法
278+
279+ 为了保持 CSS 顺序的可预测性:
280+
281+ - 尽量将 CSS 导入限制在单个 JavaScript 或 TypeScript 入口文件中
282+ - 在应用的根目录中导入全局样式和 Tailwind 样式表
283+ - 对于嵌套组件,使用 CSS 模块 (CSS Modules) 而非全局样式
284+ - 为 CSS 模块使用一致的命名约定,例如使用 ` <name>.module.css ` 而非 ` <name>.tsx `
285+ - 将共享样式提取到共享组件中以避免重复导入
286+ - 关闭自动排序导入的 linter 或格式化工具,如 ESLint 的 [ ` sort-imports ` ] ( https://eslint.org/docs/latest/rules/sort-imports )
287+ - 你可以在 ` next.config.js ` 中使用 [ ` cssChunking ` ] ( /docs/app/api-reference/config/next-config-js/cssChunking ) 选项来控制 CSS 的分块方式
288+
289+ ## 开发与生产环境 (Development vs Production)
290+
291+ - 在开发环境 (` next dev ` ) 中,CSS 更新会通过 [ 快速刷新 (Fast Refresh)] ( /docs/architecture/fast-refresh ) 即时应用
292+ - 在生产环境 (` next build ` ) 中,所有 CSS 文件会自动合并为** 多个经过压缩和代码拆分** 的 ` .css ` 文件,确保为路由加载最少数量的 CSS
293+ - 在生产环境中,即使禁用 JavaScript,CSS 仍会加载,但在开发环境中需要 JavaScript 以实现快速刷新 (Fast Refresh)
294+ - CSS 顺序在开发环境中可能表现不同,请务必检查构建 (` next build ` ) 以验证最终的 CSS 顺序
0 commit comments