Menu

CSS

Next.js 提供了几种使用 CSS 为应用添加样式的方式,包括:

Tailwind CSS

Tailwind CSS 是一个实用优先的 CSS 框架,提供了低级别的实用类来构建自定义设计。

安装 Tailwind CSS:

pnpm add -D tailwindcss @tailwindcss/postcss
npm install -D tailwindcss @tailwindcss/postcss
yarn add -D tailwindcss @tailwindcss/postcss
bun add -D tailwindcss @tailwindcss/postcss

将 PostCSS 插件添加到你的 postcss.config.mjs 文件中:

postcss.config.mjs
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
}

在全局 CSS 文件中导入 Tailwind:

app/globals.css
@import 'tailwindcss';

在根布局中导入 CSS 文件:

app/layout.tsx
TypeScript
import './globals.css'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

现在你可以开始在应用中使用 Tailwind 的实用类了:

app/page.tsx
TypeScript
export default function Page() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <h1 className="text-4xl font-bold">Welcome to Next.js!</h1>
    </main>
  )
}

值得注意的是: 如果你需要对非常旧的浏览器提供更广泛的支持,请参阅 Tailwind CSS v3 设置说明

CSS Modules

CSS Modules 通过生成唯一的类名来局部作用域化 CSS。这使你可以在不同文件中使用相同的类名而不用担心命名冲突。

要开始使用 CSS Modules,创建一个扩展名为 .module.css 的新文件,并将其导入到 app 目录内的任何组件中:

app/blog/blog.module.css
.blog {
  padding: 24px;
}
app/blog/page.tsx
TypeScript
import styles from './blog.module.css'
 
export default function Page() {
  return <main className={styles.blog}></main>
}

Global CSS

你可以使用全局 CSS 在整个应用中应用样式。

创建一个 app/global.css 文件并在根布局中导入它,以将样式应用到应用中的每个路由

app/global.css
body {
  padding: 20px 20px 60px;
  max-width: 680px;
  margin: 0 auto;
}
app/layout.tsx
TypeScript
// 这些样式应用于应用中的每个路由
import './global.css'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

值得注意的是: 全局样式可以导入到 app 目录内的任何布局、页面或组件中。然而,由于 Next.js 使用 React 内置的样式表支持来与 Suspense 集成,目前在路由之间导航时不会移除样式表,这可能导致冲突。我们建议对_真正_全局的 CSS(如 Tailwind 的基础样式)使用全局样式,对组件样式使用 Tailwind CSS,并在需要时对自定义作用域 CSS 使用 CSS Modules

External stylesheets

外部包发布的样式表可以在 app 目录的任何地方导入,包括并置的组件:

app/layout.tsx
TypeScript
import 'bootstrap/dist/css/bootstrap.css'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className="container">{children}</body>
    </html>
  )
}

值得注意的是: 在 React 19 中,也可以使用 <link rel="stylesheet" href="..." />。更多信息请参阅 React link 文档

Ordering and Merging

Next.js 在生产构建期间通过自动分块(合并)样式表来优化 CSS。CSS 的顺序取决于你在代码中导入样式的顺序

例如,base-button.module.css 将排在 page.module.css 之前,因为 <BaseButton>page.module.css 之前导入:

page.tsx
TypeScript
import { BaseButton } from './base-button'
import styles from './page.module.css'
 
export default function Page() {
  return <BaseButton className={styles.primary} />
}
base-button.tsx
TypeScript
import styles from './base-button.module.css'
 
export function BaseButton() {
  return <button className={styles.primary} />
}

Recommendations

为了保持 CSS 顺序的可预测性:

  • 尝试将 CSS 导入限制在单个 JavaScript 或 TypeScript 入口文件中
  • 在应用的根部导入全局样式和 Tailwind 样式表。
  • 使用 Tailwind CSS 满足大多数样式需求,因为它通过实用类涵盖了常见的设计模式。
  • 当 Tailwind 实用类不足时,使用 CSS Modules 处理组件特定的样式。
  • 为你的 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 才能实现 Fast Refresh。
  • CSS 顺序在开发环境中的表现可能有所不同,始终确保检查构建(next build)以验证最终的 CSS 顺序。