样式

了解如何设计你的 Nuxt 应用的样式。

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

¥Nuxt is highly flexible when it comes to styling. Write your own styles, or reference local and external stylesheets. You can use CSS preprocessors, CSS frameworks, UI libraries and Nuxt modules to style your application.

本地样式表

¥Local Stylesheets

如果你正在编写本地样式表,那么将它们放置到 assets/ 目录 中是最自然的选择。

¥If you're writing local stylesheets, the natural place to put them is the assets/ directory.

组件内导入

¥Importing Within Components

你可以直接在页面、布局和组件中导入样式表。你可以使用 JavaScript 导入或 CSS @import 声明

¥You can import stylesheets in your pages, layouts and components directly. You can use a JavaScript import, or a CSS @import statement.

pages/index.vue
<script>
// Use a static import for server-side compatibility
import '~/assets/css/first.css'

// Caution: Dynamic imports are not server-side compatible
import('~/assets/css/first.css')
</script>

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

CSS 属性

¥The CSS Property

你还可以在 Nuxt 配置中使用 css 属性。样式表的自然存放位置是 assets/ 目录。然后,你可以引用它的路径,Nuxt 会将其添加到应用的所有页面中。

¥You can also use the css property in the Nuxt configuration. The natural place for your stylesheets is the assets/ directory. You can then reference its path and Nuxt will include it to all the pages of your application.

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

使用字体

¥Working With Fonts

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

¥Place your local fonts files in your ~/public/ directory, for example in ~/public/fonts. You can then reference them in your stylesheets using 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;
}

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

¥Then reference your fonts by name in your stylesheets, pages or components:

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

通过 NPM 分发的样式表

¥Stylesheets Distributed Through NPM

你还可以引用通过 npm 分发的样式表。让我们以流行的 animate.css 库为例。

¥You can also reference stylesheets that are distributed through npm. Let's use the popular animate.css library as an example.

npm install animate.css

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

¥Then you can reference it directly in your pages, layouts and components:

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

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

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

¥The package can also be referenced as a string in the css property of your Nuxt configuration.

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

外部样式表

¥External Stylesheets

你可以通过在 nuxt.config 文件的 head 部分添加链接元素,在应用中引入外部样式表。你可以使用不同的方法实现此结果。请注意,本地样式表也可以像这样包含。

¥You can include external stylesheets in your application by adding a link element in the head section of your nuxt.config file. You can achieve this result using different methods. Note that local stylesheets can also be included like this.

你可以使用 Nuxt 配置中的 app.head 属性来操作 head 部分:

¥You can manipulate the head with the app.head property of your Nuxt configuration:

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' }]
    }
  }
})

动态添加样式表

¥Dynamically Adding Stylesheets

你可以使用 useHead 可组合项在代码中动态设置 Header 中的值。

¥You can use the useHead composable to dynamically set a value in your head in your code.

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,你可以参考其完整文档 此处

¥Nuxt uses unhead under the hood, and you can refer to its full documentation here.

使用 Nitro 插件修改渲染头部

¥Modifying The Rendered Head With A Nitro Plugin

如果你需要更高级的控制,你可以使用钩子拦截渲染的 HTML,并以编程方式修改头部。

¥If you need more advanced control, you can intercept the rendered html with a hook and modify the head programmatically.

~/server/plugins/my-plugin.ts 中创建一个插件,如下所示:

¥Create a plugin in ~/server/plugins/my-plugin.ts like this:

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 上阅读更多相关信息。

¥External stylesheets are render-blocking resources: they must be loaded and processed before the browser renders the page. Web pages that contain unnecessarily large styles take longer to render. You can read more about it on web.dev.

使用预处理器

¥Using Preprocessors

要使用 SCSS、Sass、Less 或 Stylus 等预处理器,请先安装它们。

¥To use a preprocessor like SCSS, Sass, Less or Stylus, install it first.

npm install -D sass

编写样式表的自然存放位置是 assets 目录。然后,你可以使用预处理器的语法将源文件导入到 app.vue(或布局文件)中。

¥The natural place to write your stylesheets is the assets directory. You can then import your source files in your app.vue (or layouts files) using your preprocessor's syntax.

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

或者,你可以使用 Nuxt 配置中的 css 属性。

¥Alternatively, you can use the css property of your Nuxt configuration.

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

如果你需要在预处理文件中注入代码,例如带有颜色变量的 Sass 部分,则可以使用 Vite 预处理器选项 来实现。

¥If you need to inject code in pre-processed files, like a Sass partial with color variables, you can do so with the Vite preprocessors options.

assets 目录中创建一些部分代码:

¥Create some partials in your assets directory:

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

然后在你的 nuxt.config 中:

¥Then in your nuxt.config :

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

Nuxt 默认使用 Vite。如果你希望使用 webpack,请参考每个预处理器加载器 documentation

¥Nuxt uses Vite by default. If you wish to use webpack instead, refer to each preprocessor loader documentation.

预处理器工作器(实验性)

¥Preprocessor Workers (Experimental)

Vite 已提供 实验性选项,可以使用预处理器加速。

¥Vite has made available an experimental option which can speed up using preprocessors.

你可以在 nuxt.config 中启用此功能:

¥You can enable this in your nuxt.config:


export default defineNuxtConfig({
  vite: {
    css: {
      preprocessorMaxWorkers: true // number of CPUs minus 1
    }
  }
})
这是一个实验性选项,你应该参考 Vite 文档和 provide feedback

单文件组件 (SFC) 样式

¥Single File Components (SFC) Styling

Vue 和单文件组件 (SFC) 的优点之一是它能够自然地处理样式。你可以直接在组件文件的样式块中编写 CSS 或预处理器代码,因此无需使用 CSS-in-JS 之类的工具即可获得出色的开发体验。但是,如果你希望使用 CSS-in-JS,你可以找到支持它的第三方库和模块,例如 pinceau

¥One of the best things about Vue and SFC is how great it is at naturally dealing with styling. You can directly write CSS or preprocessor code in the style block of your components file, therefore you will have fantastic developer experience without having to use something like CSS-in-JS. However if you wish to use CSS-in-JS, you can find 3rd party libraries and modules that support it, such as pinceau.

你可以参考 Vue 文档 以获得有关在 SFC 中设置组件样式的全面参考。

¥You can refer to the Vue docs for a comprehensive reference about styling components in SFC.

类和样式绑定

¥Class And Style Bindings

你可以利用 Vue SFC 功能,使用 class 和 style 属性来设置组件的样式。

¥You can leverage Vue SFC features to style your components with class and style attributes.

<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 文档

¥Refer to the Vue docs for more information.

使用 v-bind 的动态样式

¥Dynamic Styles With v-bind

你可以使用 v-bind 函数在样式块中引用 JavaScript 变量和表达式。绑定将是动态的,这意味着如果变量值发生变化,样式也会更新。

¥You can reference JavaScript variable and expression within your style blocks with the v-bind function. The binding will be dynamic, meaning that if the variable value changes, the style will be updated.

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

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

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

作用域样式

¥Scoped Styles

scoped 属性允许你单独设置组件的样式。使用此属性声明的样式仅适用于此组件。

¥The scoped attribute allows you to style components in isolation. The styles declared with this attribute will only apply to this component.

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

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

CSS 模块

¥CSS Modules

你可以将 CSS 模块 与 module 属性一起使用。使用注入的 $style 变量访问它。

¥You can use CSS Modules with the module attribute. Access it with the injected $style variable.

<template>
  <p :class="$style.red">This should be red</p>
</template>

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

预处理器支持

¥Preprocessors Support

SFC 样式块支持预处理器语法。Vite 内置对 .scss、.sass、.less、.styl 和 .stylus 文件的支持,无需配置。你只需先安装它们,它们将直接在 SFC 中使用 lang 属性。

¥SFC style blocks support preprocessors syntax. Vite come with built-in support for .scss, .sass, .less, .styl and .stylus files without configuration. You just need to install them first, and they will be available directly in SFC with the lang attribute.

<style lang="scss">
  /* Write scss here */
</style>

你可以参考 Vite CSS 文档@vitejs/plugin-vue docs。如果文件已存在,则强制覆盖它

¥You can refer to the Vite CSS docs and the @vitejs/plugin-vue docs. For webpack users, refer to the vue loader docs.

使用 PostCSS

¥Using PostCSS

Nuxt 内置了 postcss。你可以在 nuxt.config 文件中进行配置。

¥Nuxt comes with postcss built-in. You can configure it in your nuxt.config file.

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

对于 目录中的静态文件(例如 PDF 或图片),请使用 属性来确保链接正确解析。

¥For proper syntax highlighting in SFC, you can use the postcss lang attribute.

<style lang="postcss">
  /* Write postcss here */
</style>

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

¥By default, Nuxt comes with the following plugins already pre-configured:

利用布局实现多种样式

¥Leveraging Layouts For Multiple Styles

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

¥If you need to style different parts of your application completely differently, you can use layouts. Use different styles for different layouts.

<template>
  <div class="default-layout">
    <h1>Default Layout</h1>
    <slot />
  </div>
</template>

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

第三方库和模块

¥Third Party Libraries And Modules

Nuxt 在样式方面没有有态度,并为你提供了多种选择。你可以使用任何你想要的样式工具,例如 UnoCSSTailwind CSS 等热门库。

¥Nuxt isn't opinionated when it comes to styling and provides you with a wide variety of options. You can use any styling tool that you want, such as popular libraries like UnoCSS or Tailwind CSS.

社区和 Nuxt 团队开发了大量 Nuxt 模块,使集成更加便捷。你可以在网站的 模块部分 上找到它们。以下是一些帮助你入门的模块:

¥The community and the Nuxt team have developed plenty of Nuxt modules to make the integration easier. You can discover them on the modules section of the website. Here are a few modules to help you get started:

Nuxt 模块为你提供了开箱即用的良好开发体验,但请记住,如果你最喜欢的工具没有模块,并不意味着你不能在 Nuxt 中使用它!你可以根据自己的项目自行配置。根据工具的不同,你可能需要使用 Nuxt 插件 和/或 创建你自己的模块。如果需要,请与 community 共享!

¥Nuxt modules provide you with a good developer experience out of the box, but remember that if your favorite tool doesn't have a module, it doesn't mean that you can't use it with Nuxt! You can configure it yourself for your own project. Depending on the tool, you might need to use a Nuxt plugin and/or make your own module. Share them with the community if you do!

轻松加载 Web 字体

¥Easily Load Webfonts

你可以使用 Nuxt Google Fonts 模块 加载 Google 字体。

¥You can use the Nuxt Google Fonts module to load Google Fonts.

如果你使用 UnoCSS,请注意它附带 Web 字体预设,以便方便地从常见字体提供商(包括 Google Fonts 等)加载字体。

¥If you are using UnoCSS, note that it comes with a web fonts presets to conveniently load fonts from common providers, including Google Fonts and more.

高级

¥Advanced

过渡

¥Transitions

Nuxt 拥有与 Vue 相同的 <Transition> 元素,并且还支持实验性的 视图转换 API

¥Nuxt comes with the same <Transition> element that Vue has, and also has support for the experimental View Transitions API.

Read more in Docs > Getting Started > Transitions.

字体高级优化

¥Font Advanced Optimization

我们建议使用 Fontaine 来减少 CLS 的使用。如果你需要更高级的功能,请考虑创建一个 Nuxt 模块来扩展构建过程或 Nuxt 运行时。

¥We would recommend using Fontaine to reduce your CLS. If you need something more advanced, consider creating a Nuxt module to extend the build process or the Nuxt runtime.

请始终牢记,充分利用 Web 生态系统中可用的各种工具和技术,使你的应用样式设置更轻松、更高效。无论你使用的是原生 CSS、预处理器、postcss、UI 库还是模块,Nuxt 都能满足你的需求。祝你样式设置愉快!

LCP 高级优化

¥LCP Advanced Optimizations

你可以执行以下操作来加快全局 CSS 文件的下载速度:

¥You can do the following to speed-up the download of your global CSS files:

  • 使用 CDN,使文件在物理上更靠近用户
  • 压缩你的资源,最好使用 Brotli
  • 使用 HTTP2/HTTP3 进行传输
  • 将你的资源托管在同一域名下(请勿使用其他子域名)

如果你使用的是 Cloudflare、Netlify 或 Vercel 等现代平台,上述大部分操作应该会自动补齐。你可以在 web.dev 上找到 LCP 优化指南。

¥Most of these things should be done for you automatically if you're using modern platforms like Cloudflare, Netlify or Vercel. You can find an LCP optimization guide on web.dev.

如果你的所有 CSS 都由 Nuxt 内联,你可以(实验性地)完全阻止在渲染的 HTML 中引用外部 CSS 文件。你可以使用钩子来实现这一点,该钩子可以放置在模块中,也可以放置在 Nuxt 配置文件中。

¥If all of your CSS is inlined by Nuxt, you can (experimentally) completely stop external CSS files from being referenced in your rendered HTML. You can achieve that with a hook, that you can place in a module, or in your Nuxt configuration file.

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'build:manifest': (manifest) => {
      // find the app entry, css list
      const css = Object.values(manifest).find(options => options.isEntry)?.css
      if (css) {
        // start from the end of the array and go to the beginning
        for (let i = css.length - 1; i >= 0; i--) {
          // if it starts with 'entry', remove it from the list
          if (css[i].startsWith('entry')) css.splice(i, 1)
        }
      }
    },
  },
})