---
title: "样式设置"
description: "了解如何为您的 Nuxt 应用程序设置样式。"
canonical_url: "https://nuxt.zhcndoc.com/docs/3.x/getting-started/styling"
---
# 样式设置

> 了解如何为您的 Nuxt 应用程序设置样式。

Nuxt 在样式方面非常灵活。您可以编写自己的样式，或引用本地和外部样式表。  
您可以使用 CSS 预处理器、CSS 框架、UI 库和 Nuxt 模块来为您的应用程序设置样式。

## 本地样式表

如果您要编写本地样式表，最合适的位置是 [`assets/` 目录](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/assets)。

### 在组件中导入

您可以直接在页面、布局和组件中导入样式表。  
您可以使用 JavaScript 的 import，或者 CSS 的 [`@import` 语句](https://developer.mozilla.org/en-US/docs/Web/CSS/@import)。

```vue [pages/index.vue]
<script>
// 使用静态导入以兼容服务端
import '~/assets/css/first.css'

// 注意：动态导入不兼容服务端
import('~/assets/css/first.css')
</script>

<style>
@import url("~/assets/css/second.css");
</style>
```

::tip
样式表将内嵌在 Nuxt 渲染的 HTML 中。
::

### css 属性

您也可以在 Nuxt 配置中使用 `css` 属性。
样式表最合适的位置是 [`assets/` 目录](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/assets)。然后，您可以引用其路径，Nuxt 会将其包含在应用程序的所有页面中。

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  css: ['~/assets/css/main.css'],
})
```

::tip
样式表将内嵌在 Nuxt 渲染的 HTML 中，注入为全局样式，且应用于所有页面。
::

### 字体的使用

将本地字体文件放置在 `~/public/` 目录中，例如 `~/public/fonts`。然后可以在样式表中使用 `url()` 方式引用它们。

```css [assets/css/main.css]
@font-face {
  font-family: 'FarAwayGalaxy';
  src: url('/fonts/FarAwayGalaxy.woff') format('woff');
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}
```

然后在样式表、页面或组件中通过名称引用字体：

```vue
<style>
h1 {
  font-family: 'FarAwayGalaxy', sans-serif;
}
</style>
```

### 通过 NPM 分发的样式表

您也可以引用通过 npm 分发的样式表。以流行的 `animate.css` 库为例。

::code-group{sync="pm"}
```bash [npm]
npm install animate.css
```

```bash [yarn]
yarn add animate.css
```

```bash [pnpm]
pnpm install animate.css
```

```bash [bun]
bun install animate.css
```

```bash [deno]
deno install npm:animate.css
```
::

然后可以直接在页面、布局和组件中引用：

```vue [app.vue]
<script>
import 'animate.css'
</script>

<style>
@import url("animate.css");
</style>
```

该包也可以在 Nuxt 配置的 css 属性中以字符串形式引用。

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  css: ['animate.css'],
})
```

## 外部样式表

您可以通过在 nuxt.config 文件的 head 部分添加 link 标签来引入外部样式表。可以通过多种方式实现此效果。请注意，本地样式表也可以这样引入。

您可以使用 Nuxt 配置中的 [`app.head`](https://nuxt.zhcndoc.com/docs/3.x/api/nuxt-config#head) 属性来操作 head：

```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
  app: {
    head: {
      link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }],
    },
  },
})
```

### 动态添加样式表

您可以在代码中使用 useHead 组合式函数动态设置 head 的值。

::read-more{to="https://nuxt.zhcndoc.com/docs/3.x/api/composables/use-head"}
::

```ts twoslash
useHead({
  link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }],
})
```

Nuxt 在底层使用 `unhead`，您可以参考 [完整文档](https://unhead.unjs.io)。

### 使用 Nitro 插件修改渲染的 head

如果您需要更高级的控制，您可以通过钩子拦截渲染后的 html，并通过代码修改 head。

像这样在 `~~/server/plugins/my-plugin.ts` 中创建一个插件：

<!-- TODO: figure out how to use twoslash to inject types for a different context -->

```ts [server/plugins/my-plugin.ts]
export default defineNitroPlugin((nitro) => {
  nitro.hooks.hook('render:html', (html) => {
    html.head.push('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css">')
  })
})
```

外部样式表是阻塞渲染资源：必须在浏览器渲染页面前加载和处理。包含不必要大文件的网页会更慢。您可以在 [web.dev](https://web.dev/defer-non-critical-css) 阅读更多相关内容。

## 使用预处理器

使用 SCSS、Sass、Less 或 Stylus 等预处理器，需先安装对应依赖。

::code-group
```bash [Sass & SCSS]
npm install -D sass
```

```bash [Less]
npm install -D less
```

```bash [Stylus]
npm install -D stylus
```
::

自然地，您会将样式文件放在 `assets` 目录。  
然后您可以使用对应预处理器语法在 `app.vue`（或布局文件）中导入源文件。

```vue [pages/app.vue]
<style lang="scss">
@use "~/assets/scss/main.scss";
</style>
```

或者使用 Nuxt 配置里的 `css` 属性：

```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
  css: ['~/assets/scss/main.scss'],
})
```

::tip
这两种方式，编译后的样式都内嵌在 Nuxt 渲染的 HTML 中。
::

如果您需要在预处理文件中注入代码，比如带有颜色变量的 [Sass partial](https://sass-lang.com/documentation/at-rules/use#partials)，可以通过 Vite 的 [preprocessorOptions](https://vite.dev/config/shared-options#css-preprocessoroptions) 实现。

在 `assets` 目录中创建 partials：

::code-group{sync="preprocessor"}
```scss [assets/_colors.scss]
$primary: #49240F;
$secondary: #E4A79D;
```

```sass [assets/_colors.sass]
$primary: #49240F
$secondary: #E4A79D
```
::

然后在 `nuxt.config` 中配置：

::code-group
```ts twoslash [SCSS]
export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "~/assets/_colors.scss" as *;',
        },
      },
    },
  },
})
```

```ts twoslash [SASS]
export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorOptions: {
        sass: {
          additionalData: '@use "~/assets/_colors.sass" as *\n',
        },
      },
    },
  },
})
```
::

Nuxt 默认使用 Vite，若想使用 webpack，请参考相应的预处理器 loader 文档：[sass-loader](https://webpack.js.org/loaders/sass-loader)。

### 预处理器 Workers（实验性）

Vite 提供了一个 [实验性选项](https://vite.dev/config/shared-options#css-preprocessormaxworkers) ，可加速使用预处理器。

你可以在 `nuxt.config` 中启用：

```ts
export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorMaxWorkers: true // CPU 核心数减 1
    }
  }
})
```

::note
这是实验性功能，请参考 Vite 文档并[提供反馈](https://github.com/vitejs/vite/discussions/15835)。
::

## 单文件组件（SFC）样式

Vue 和 SFC 的最大优势之一是很好地支持样式。您可以直接在组件文件的 style 块中写 CSS 或预处理器代码，获得极佳的开发体验，无需使用 CSS-in-JS 等方案。如果您想用 CSS-in-JS，也可以找到第三方库和模块支持，例如 [pinceau](https://github.com/Tahul/pinceau)。

您可以参考 [Vue 文档](https://vuejs.org/api/sfc-css-features) 获取关于 SFC 组件样式的完整参考。

### Class 和 Style 绑定

您可以利用 Vue SFC 功能，通过 class 和 style 属性为组件设置样式。

::code-group
```vue [Ref and Reactive]
<script setup lang="ts">
const isActive = ref(true)
const hasError = ref(false)
const classObject = reactive({
  'active': true,
  'text-danger': false,
})
</script>

<template>
  <div
    class="static"
    :class="{ 'active': isActive, 'text-danger': hasError }"
  />
  <div :class="classObject" />
</template>
```

```vue [Computed]
<script setup lang="ts">
const isActive = ref(true)
const error = ref(null)

const classObject = computed(() => ({
  'active': isActive.value && !error.value,
  'text-danger': error.value && error.value.type === 'fatal',
}))
</script>

<template>
  <div :class="classObject" />
</template>
```

```vue [Array]
<script setup lang="ts">
const isActive = ref(true)
const errorClass = ref('text-danger')
</script>

<template>
  <div :class="[{ active: isActive }, errorClass]" />
</template>
```

```vue [Style]
<script setup lang="ts">
const activeColor = ref('red')
const fontSize = ref(30)
const styleObject = reactive({ color: 'red', fontSize: '13px' })
</script>

<template>
  <div :style="{ color: activeColor, fontSize: fontSize + 'px' }" />
  <div :style="[baseStyles, overridingStyles]" />
  <div :style="styleObject" />
</template>
```
::

详情请参考 [Vue 文档](https://vuejs.org/guide/essentials/class-and-style.html)。

### 使用 `v-bind` 动态样式

您可以在 style 块中使用 v-bind 函数引用 JavaScript 变量和表达式。  
绑定是动态的，即变量值改变时，样式也随之更新。

```vue
<script setup lang="ts">
const color = ref('red')
</script>

<template>
  <div class="text">
    hello
  </div>
</template>

<style>
.text {
  color: v-bind(color);
}
</style>
```

### Scoped 样式

`scoped` 属性允许您对组件样式进行隔离。带有该属性的样式只作用于当前组件。

```vue
<template>
  <div class="example">
    hi
  </div>
</template>

<style scoped>
.example {
  color: red;
}
</style>
```

### CSS 模块

您可以使用带有 `module` 属性的 [CSS Modules](https://github.com/css-modules/css-modules)。通过注入的 `$style` 变量访问。

```vue
<template>
  <p :class="$style.red">这段文字应该是红色的</p>
</template>

<style module>
.red {
  color: red;
}
</style>
```

### 预处理器支持

SFC 的 style 块支持预处理器语法。Vite 内建支持 .scss, .sass, .less, .styl 和 .stylus 等，无需配置。只需先安装对应预处理器即可，随后在 SFC 中通过 lang 属性直接使用。

::code-group
```vue [SCSS]
<style lang="scss">
  /* 在这里书写 scss */
</style>
```

```vue [Sass]
<style lang="sass">
  /* 在这里书写 sass */
</style>
```

```vue [LESS]
<style lang="less">
  /* 在这里书写 less */
</style>
```

```vue [Stylus]
<style lang="stylus">
  /* 在这里书写 stylus */
</style>
```
::

您可以参考 [Vite CSS 文档](https://vite.dev/guide/features#css) 和 [@vitejs/plugin-vue 文档](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue)。  
webpack 用户请参考 [vue-loader 文档](https://vue-loader.vuejs.org)。

## 使用 PostCSS

Nuxt 内置了 postcss。您可以在 `nuxt.config` 文件中配置它。

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  postcss: {
    plugins: {
      'postcss-nested': {},
      'postcss-custom-media': {},
    },
  },
})
```

为了在 SFC 中正确高亮语法，您可以使用 postcss 的 lang 属性。

```vue
<style lang="postcss">
  /* 在这里书写 postcss */
</style>
```

默认情况下，Nuxt 已预配置以下插件：

- [postcss-import](https://github.com/postcss/postcss-import)：增强 `@import` 规则
- [postcss-url](https://github.com/postcss/postcss-url)：转换 `url()` 语句
- [autoprefixer](https://github.com/postcss/autoprefixer)：自动添加厂商前缀
- [cssnano](https://cssnano.github.io/cssnano)：压缩和清理

## 通过布局实现多样式

如果你需要用完全不同的样式来设计应用的不同部分，你可以使用布局。  
为不同的布局使用不同的样式。

```vue
<template>
  <div class="default-layout">
    <h1>默认布局</h1>
    <slot />
  </div>
</template>

<style>
.default-layout {
  color: red;
}
</style>
```

::read-more{to="https://nuxt.zhcndoc.com/docs/3.x/directory-structure/layouts"}
::

## 第三方库和模块

Nuxt 对于样式不设限，提供了丰富的选择。您可以用任何想用的样式工具，如流行的库 [UnoCSS](https://unocss.zhcndoc.com) 或 [Tailwind CSS](https://tailwindcss.zhcndoc.com)。

社区和 Nuxt 团队开发了大量 Nuxt 模块来简化集成。  
您可在官网的 [模块部分](https://nuxt.zhcndoc.com/modules) 发现更多。  
这里列举一些助您快速起步的模块：

- [UnoCSS](https://nuxt.zhcndoc.com/modules/unocss)：即时按需的原子 CSS 引擎
- [Tailwind CSS](https://nuxt.zhcndoc.com/modules/tailwindcss)：实用优先的 CSS 框架
- [Fontaine](https://github.com/nuxt-modules/fontaine)：字体度量回退
- [Pinceau](https://github.com/Tahul/pinceau)：可适配的样式框架
- [Nuxt UI](https://ui.nuxt.com)：现代 Web 应用 UI 库
- [Panda CSS](https://panda-css.com/docs/installation/nuxt)：构建时生成原子 CSS 的 CSS-in-JS 引擎

Nuxt 模块开箱即为您提供良好的开发体验，但请记住，如果您喜欢的工具没有对应的模块，并不意味着它无法与 Nuxt 一起使用！您可以为自己的项目自行配置。根据工具的不同，您可能需要使用 [Nuxt 插件](https://nuxt.zhcndoc.com/docs/3.x/directory-structure/plugins) 和/或[创建自己的模块](https://nuxt.zhcndoc.com/docs/3.x/guide/modules)。如果您这么做了，欢迎与[社区](https://nuxt.zhcndoc.com/modules)分享！

### 轻松加载 Web 字体

您可以使用 [Nuxt Google Fonts 模块](https://github.com/nuxt-modules/google-fonts) 来加载 Google Fonts。

如果您使用的是 [UnoCSS](https://unocss.zhcndoc.com/integrations/nuxt)，它自带 [Web 字体预设](https://unocss.zhcndoc.com/presets/web-fonts)，方便加载来自常用提供者的字体，包括 Google Fonts 等。

## 高级

### 过渡动画

Nuxt 自带与 Vue 相同的 `<Transition>` 元素，并且还支持实验性的 [View Transitions API](https://nuxt.zhcndoc.com/docs/3.x/getting-started/transitions#view-transitions-api-experimental)。

::read-more{to="https://nuxt.zhcndoc.com/docs/3.x/getting-started/transitions"}
::

### 字体高级优化

我们推荐使用 [Fontaine](https://github.com/nuxt-modules/fontaine) 来降低您的 [CLS](https://web.dev/cls)。如果需要更高级功能，可以考虑创建 Nuxt 模块来扩展构建流程或运行时。

::tip
请务必利用 Web 生态中的各种工具和技巧，使您的应用样式更轻松、高效。无论是原生 CSS、预处理器、postcss、UI 库或模块，Nuxt 都能满足您的需求。祝您样式愉快！
::

### LCP（最大内容绘制）高级优化

您可以通过以下措施加快全局 CSS 文件的下载速度：

- 使用 CDN 让文件物理上更接近用户
- 压缩资源，最好使用 Brotli
- 通过 HTTP2/HTTP3 进行传输
- 资源放在同一域名下（避免用不同子域）

若您使用 Cloudflare、Netlify 或 Vercel 等现代平台，这些通常会自动帮您完成。  
您可以在 [web.dev](https://web.dev/optimize-lcp) 查看 LCP 优化指南。

如果所有 CSS 都由 Nuxt 内联，您可以（实验性地）完全禁止外部 CSS 文件在渲染的 HTML 中被引用。  
您可以用钩子实现，放在模块或 Nuxt 配置文件中。

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  hooks: {
    'build:manifest': (manifest) => {
      // 找到应用入口的 CSS 列表
      const css = Object.values(manifest).find(options => options.isEntry)?.css
      if (css) {
        // 从数组末尾向前遍历
        for (let i = css.length - 1; i >= 0; i--) {
          // 以 'entry' 开头的 CSS，从列表中移除
          if (css[i].startsWith('entry')) css.splice(i, 1)
        }
      }
    },
  },
})
```


## Sitemap

See the full [sitemap](https://nuxt.zhcndoc.com/sitemap.md) for all pages.
