如何在应用中使用 CSS
Next.js 提供了多种在应用中使用 CSS 的方式,包括:
CSS 模块 (CSS Modules)
CSS 模块通过生成唯一的类名来实现 CSS 的局部作用域,这样您可以在不同文件中使用相同的类名而无需担心命名冲突。
要开始使用 CSS 模块,请创建一个扩展名为 .module.css
的新文件,并将其导入到 pages
目录中的任意组件:
.blog {
padding: 24px;
}
import styles from './blog.module.css'
export default function Page() {
return <main className={styles.blog}></main>
}
import styles from './blog.module.css'
export default function Page() {
return <main className={styles.blog}></main>
}
全局 CSS (Global CSS)
您可以使用全局 CSS 来为整个应用应用样式。
将样式表导入 pages/_app.js
文件,这样样式将应用到应用中的每个路由:
import '@/styles/global.css'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
由于样式表的全局性质,为避免冲突,您应该在 pages/_app.js
中导入它们。
外部样式表 (External Stylesheets)
Next.js 允许您从 JavaScript 文件导入 CSS 文件。这是可能的,因为 Next.js 扩展了 import
的概念,使其不仅限于 JavaScript。
从 node_modules
导入样式
自 Next.js 9.5.4 起,允许从 node_modules
导入 CSS 文件到应用中的任何位置。
对于全局样式表,如 bootstrap
或 nprogress
,您应该在 pages/_app.js
中导入文件。例如:
import 'bootstrap/dist/css/bootstrap.css'
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
对于第三方组件所需的 CSS,您可以在组件中导入。例如:
import { useState } from 'react'
import { Dialog } from '@reach/dialog'
import VisuallyHidden from '@reach/visually-hidden'
import '@reach/dialog/styles.css'
function ExampleDialog(props) {
const [showDialog, setShowDialog] = useState(false)
const open = () => setShowDialog(true)
const close = () => setShowDialog(false)
return (
<div>
<button onClick={open}>打开对话框</button>
<Dialog isOpen={showDialog} onDismiss={close}>
<button className="close-button" onClick={close}>
<VisuallyHidden>关闭</VisuallyHidden>
<span aria-hidden>×</span>
</button>
<p>你好,我是一个对话框</p>
</Dialog>
</div>
)
}
排序与合并 (Ordering and Merging)
Next.js 在生产构建时会通过自动分块(合并)样式表来优化 CSS。CSS 的顺序取决于您在代码中导入样式的顺序。
例如,base-button.module.css
会排在 page.module.css
之前,因为 <BaseButton>
在 page.module.css
之前导入:
import { BaseButton } from './base-button'
import styles from './page.module.css'
export default function Page() {
return <BaseButton className={styles.primary} />
}
import { BaseButton } from './base-button'
import styles from './page.module.css'
export default function Page() {
return <BaseButton className={styles.primary} />
}
推荐做法
为了保持 CSS 顺序的可预测性:
- 尽量将 CSS 导入限制在单个 JavaScript 或 TypeScript 入口文件中
- 在应用的根目录中导入全局样式和 Tailwind 样式表
- 对于嵌套组件,使用 CSS 模块而非全局样式
- 为 CSS 模块使用一致的命名约定。例如,使用
<name>.module.css
而非<name>.tsx
- 将共享样式提取到共享组件中以避免重复导入
- 关闭自动排序导入的 linter 或格式化工具,如 ESLint 的
sort-imports
- 您可以在
next.config.js
中使用cssChunking
选项来控制 CSS 的分块方式
开发与生产环境 (Development vs Production)
- 在开发环境 (
next dev
) 中,CSS 更新会通过 快速刷新 (Fast Refresh) 即时应用 - 在生产环境 (
next build
) 中,所有 CSS 文件会自动合并为多个经过压缩和代码拆分的.css
文件,确保为路由加载最少数量的 CSS - 在生产环境中,即使禁用 JavaScript,CSS 仍会加载,但在开发环境中需要 JavaScript 来实现快速刷新
- CSS 顺序在开发环境中可能表现不同,请务必检查构建 (
next build
) 以验证最终的 CSS 顺序