样式设置

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

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

本地样式表

如果您正在编写本地样式表,自然的放置位置是 assets/ 目录

在组件中导入

您可以直接在页面、布局和组件中导入样式表。
您可以使用 JavaScript 的 import,或者 CSS 的 @import 语句

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

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

<style>
@import url("~/assets/css/second.css");
</style>
样式表将内嵌在 Nuxt 渲染的 HTML 中。

css 属性

您也可以在 Nuxt 配置中使用 css 属性。
样式表的自然放置位置是 assets/ 目录,您可以引用它们的路径,Nuxt 会将其包含到应用的所有页面中。

nuxt.config.ts
export default defineNuxtConfig({
  css: ['~/assets/css/main.css']
})
样式表将内嵌在 Nuxt 渲染的 HTML 中,注入为全局样式,且应用于所有页面。

字体的使用

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

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;
}

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

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

通过 NPM 分发的样式表

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

npm install animate.css

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

app.vue
<script>
import 'animate.css'
</script>

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

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

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

外部样式表

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

您可以通过 Nuxt 配置的 app.head 属性操作 head:

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 in Docs > API > Composables > Use Head.
useHead({
  link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
})

Nuxt 在底层使用 unhead,您可以参考 完整文档

使用 Nitro 插件修改渲染的 head

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

~/server/plugins/my-plugin.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 阅读更多相关内容。

使用预处理器

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

npm install -D sass

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

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

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

nuxt.config.ts
export default defineNuxtConfig({
  css: ['~/assets/scss/main.scss']
})
这两种方式,编译后的样式都内嵌在 Nuxt 渲染的 HTML 中。

如果您需要在预处理文件中注入代码,比如带有颜色变量的 Sass partial,可以通过 Vite 的 preprocessorOptions 实现。

assets 目录中创建 partials:

$primary: #49240F;
$secondary: #E4A79D;

然后在 nuxt.config 中配置:

export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorOptions: {
        scss: {
          additionalData: '@use "~/assets/_colors.scss" as *;'
        }
      }
    }
  }
})

Nuxt 默认使用 Vite,若想使用 webpack,请参考相应的预处理器 loader 文档:sass-loader

预处理器 Workers(实验性)

Vite 提供了一个 实验性选项 ,可加速使用预处理器。

你可以在 nuxt.config 中启用:


export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorMaxWorkers: true // CPU 核心数减 1
    }
  }
})
这是实验性功能,请参考 Vite 文档并提供反馈

单文件组件(SFC)样式

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

您可以参考 Vue 文档 获取关于 SFC 组件样式的完整参考。

Class 和 Style 绑定

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

<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>
  <div :class="classObject"></div>
</template>

详情请参考 Vue 文档

使用 v-bind 动态样式

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

<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 属性允许您对组件样式进行隔离。带有该属性的样式只作用于当前组件。

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

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

CSS 模块

您可以使用带有 module 属性的 CSS Modules。通过注入的 $style 变量访问。

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

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

预处理器支持

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

<style lang="scss">
  /* 在这里书写 scss */
</style>

您可以参考 Vite CSS 文档@vitejs/plugin-vue 文档
webpack 用户请参考 vue-loader 文档

使用 PostCSS

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

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

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

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

默认情况下,Nuxt 已预配置以下插件:

通过布局实现多样式

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

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

<style>
.default-layout {
  color: red;
}
</style>
Read more in Docs > Guide > Directory Structure > Layouts.

第三方库和模块

Nuxt 对于样式不设限,提供了丰富的选择。您可以用任何想用的样式工具,如流行的库 UnoCSSTailwind CSS

社区和 Nuxt 团队开发了大量 Nuxt 模块来简化集成。
您可在官网的 modules 部分 发现更多。
这里列举一些助您快速起步的模块:

Nuxt 模块为开发者提供了极佳的体验,但请记住,如果您喜欢的工具没有模块,也并不意味着不能用 Nuxt。您可以自行配置,视工具而定,可能需要用到 Nuxt 插件 和/或 自制模块。如果愿意,也欢迎您分享给社区

轻松加载 Web 字体

您可以使用 Nuxt Google Fonts 模块 来加载 Google Fonts。

如果您使用的是 UnoCSS,它自带 web fonts 预设,方便加载来自常用提供者的字体,包括 Google Fonts 等。

高级

过渡动画

Nuxt 内置了与 Vue 相同的 <Transition> 组件,同时支持实验性的 View Transitions API

Read more in Docs > Getting Started > Transitions.

字体高级优化

我们推荐使用 Fontaine 来降低您的 CLS。如果需要更高级功能,可以考虑创建 Nuxt 模块来扩展构建流程或运行时。

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

LCP(最大内容绘制)高级优化

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

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

若您使用 Cloudflare、Netlify 或 Vercel 等现代平台,这些通常会自动帮您完成。
您可以在 web.dev 查看 LCP 优化指南。

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

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'build:manifest': (manifest) => {
      // 找到 app 入口的 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)
        }
      }
    },
  },
})