Menu

如何在应用中使用 CSS

Next.js 提供了几种在应用中使用 CSS 的方式,包括:

本页将指导你如何使用这些方法。

CSS Modules

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

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

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

全局 CSS

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

要使用全局样式,创建一个新的 CSS 文件,例如 app/global.css

app/global.css
body {
  padding: 20px 20px 60px;
  max-width: 680px;
  margin: 0 auto;
}

在根布局(app/layout.js)中导入该文件,以将样式应用到应用中的每个路由

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,而对于作用域 CSS 则使用 CSS Modules

Tailwind CSS

Tailwind CSS 是一个实用优先的 CSS 框架,可以与 Next.js 无缝集成。

安装 Tailwind

要开始使用 Tailwind,安装必要的 Tailwind CSS 包:

Terminal
npm install -D tailwindcss @tailwindcss/postcss postcss

配置 Tailwind

在项目根目录创建一个 postcss.config.mjs 文件,并将 @tailwindcss/postcss 插件添加到你的 PostCSS 配置中:

postcss.config.mjs
/** @type {import('tailwindcss').Config} */
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
}

使用 Tailwind

Tailwind 指令 添加到你的全局样式表中:

app/globals.css
@import 'tailwindcss';

然后,在根布局中导入样式:

app/layout.tsx
TypeScript
import type { Metadata } from 'next'
 
// 这些样式适用于应用中的每个路由
import './globals.css'
 
export const metadata: Metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}
 
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 <h1 className="text-3xl font-bold underline">Hello, Next.js!</h1>
}

Sass

Next.js 集成了 Sass,支持 .scss.sass 扩展名和语法。

你也可以通过 CSS Modules.module.scss.module.sass 扩展名使用组件级 Sass。

安装 Sass

要开始使用 Sass,安装 sass 包:

Terminal
npm install --save-dev sass

自定义 Sass 选项

如果你想配置 Sass 选项,请在 next.config.js 中使用 sassOptions 选项。

next.config.ts
TypeScript
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  sassOptions: {
    additionalData: `$var: red;`,
  },
}
 
export default nextConfig

CSS-in-JS

**警告:**需要运行时 JavaScript 的 CSS-in-JS 库目前在 React Server Components 中不受支持。在较新的 React 功能(如 Server Components 和 Streaming)中使用 CSS-in-JS 需要库作者支持最新版本的 React。

以下库在 app 目录的客户端组件中受支持(按字母顺序排列):

以下库目前正在开发支持:

如果你想为 Server Components 添加样式,我们建议使用 CSS Modules 或其他输出 CSS 文件的解决方案,如 Tailwind CSS

配置 CSS-in-JS

要配置 CSS-in-JS,你需要:

  1. 创建一个样式注册表来收集渲染中的所有 CSS 规则。
  2. 使用 useServerInsertedHTML 钩子在可能使用这些规则的任何内容之前注入规则。
  3. 创建一个客户端组件,在初始服务器端渲染期间用样式注册表包装你的应用。

styled-jsx

要为你的应用配置 styled-jsx,创建一个新的注册表:

app/registry.tsx
TypeScript
'use client'
 
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'
 
export default function StyledJsxRegistry({
  children,
}: {
  children: React.ReactNode
}) {
  // 仅使用惰性初始状态创建一次样式表
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [jsxStyleRegistry] = useState(() => createStyleRegistry())
 
  useServerInsertedHTML(() => {
    const styles = jsxStyleRegistry.styles()
    jsxStyleRegistry.flush()
    return <>{styles}</>
  })
 
  return <StyleRegistry registry={jsxStyleRegistry}>{children}</StyleRegistry>
}

然后,用注册表包装你的根布局

app/layout.tsx
TypeScript
import StyledJsxRegistry from './registry'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledJsxRegistry>{children}</StyledJsxRegistry>
      </body>
    </html>
  )
}

styled-components

要使用 styled-components,在 next.config.js 中启用它:

next.config.ts
TypeScript
import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  compiler: {
    styledComponents: true,
  },
}
 
export default nextConfig

然后,使用 styled-components API 创建一个全局注册表组件,收集渲染期间生成的所有 CSS 样式规则,以及一个返回这些规则的函数。然后使用 useServerInsertedHTML 钩子将在注册表中收集的样式注入到根布局的 <head> HTML 标签中。

lib/registry.tsx
TypeScript
'use client'
 
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
 
export default function StyledComponentsRegistry({
  children,
}: {
  children: React.ReactNode
}) {
  // 仅使用惰性初始状态创建一次样式表
  // x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
 
  useServerInsertedHTML(() => {
    const styles = styledComponentsStyleSheet.getStyleElement()
    styledComponentsStyleSheet.instance.clearTag()
    return <>{styles}</>
  })
 
  if (typeof window !== 'undefined') return <>{children}</>
 
  return (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children}
    </StyleSheetManager>
  )
}

用样式注册表组件包装根布局的 children

app/layout.tsx
TypeScript
import StyledComponentsRegistry from './lib/registry'
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html>
      <body>
        <StyledComponentsRegistry>{children}</StyledComponentsRegistry>
      </body>
    </html>
  )
}

外部样式表

外部包发布的样式表可以在 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>
  )
}

外部样式表必须直接从 npm 包导入或下载并与你的代码库共存。你不能使用 <link rel="stylesheet" />