样式 Styling

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

本地样式表

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

在组件内导入

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

pages/index.vue
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
ts
export default defineNuxtConfig({
  css: ['~/assets/css/main.css']
})

样式表将内联在 Nuxt 渲染的 HTML 中,全局注入并出现在所有页面中。

使用web字体

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

assets/css/main.css
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库作为示例。

bash
npm install animate.css

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

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

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

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

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

外部样式表

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

您可以使用 Nuxt 配置的 app.head 属性来操作头部:

nuxt.config.ts
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 中的值。

:

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

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

使用 Nitro 插件修改渲染的头部

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

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

server/plugins/my-plugin.ts
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 等预处理器,请先安装它。

bash
Sass & SCSS
bash
npm install sass

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

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

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

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

在这两种情况下,编译后的样式表将内联到 Nuxt 渲染的 HTML 中。

如果您需要在预处理文件中注入代码,例如带有颜色变量的 sass 部分,您可以使用 vite 来执行此操作 预处理器选项

在“assets”目录中创建一些部分:

scss
assets/_colors.scss
scss
$primary: #49240F;
$secondary: #E4A79D;

然后在你的 nuxt.config 中:

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

Nuxt默认使用Vite。 如果您想改用 webpack,请参阅每个预处理器加载器 文档

单文件组件 (SFC) 样式

Vue 和 SFC 最好的事情之一就是它在自然处理样式方面的出色表现。 您可以直接在组件文件的样式块中编写CSS或预处理器代码,因此您将获得出色的开发体验,而无需使用CSS-in-JS之类的东西。 但是,如果您希望使用 CSS-in-JS,您可以找到支持它的第三方库和模块,例如 pinceau

您可以参考 Vue 文档 以获取有关 SFC 中样式组件的全面参考。

类和样式绑定

您可以利用 Vue SFC 功能通过类和样式属性来设计组件的样式。

vue
Ref and Reactive
vue
<script setup>
const isActive = ref(true)
const hasError = ref(false)
const classObject = reactive({
  'active': true,
  'text-danger': false
})
</script>

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

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

有关更多信息,请参阅 Vue 文档

使用 v-bind 的动态样式

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

vue
<script setup>
const color = ref('red')
</script>

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

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

范围样式

scoped 属性允许您在阳光下设置组件的样式。 使用此属性声明的样式仅适用于该组件。

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

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

CSS 模块

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

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

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

预处理器支持

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

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

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

使用 PostCSS

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

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

为了在 SFC 中正确突出显示语法,您可以使用 postcss lang 属性。

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

默认情况下,Nuxt 附带了以下已预先配置的插件:

利用多种样式的布局

如果您需要对应用程序的不同部分进行完全不同的设计,则可以使用布局。 不同的布局使用不同的样式。

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

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

第三方库和模块

Nuxt 在样式方面并不固执己见,并为您提供了多种选择。 您可以使用任何所需的样式工具,例如 UnoCSSTailwind CSS 等流行库。

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

Nuxt 模块为您提供开箱即用的良好开发人员体验,但请记住,如果您最喜欢的工具没有模块,并不意味着您不能将其与 Nuxt 一起使用! 您可以为自己的项目自行配置。 根据工具的不同,您可能需要使用 Nuxt 插件 和/或 制作您自己的模块。 如果您愿意,请与社区分享!

轻松加载网络字体

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

如果您使用 UnoCSS,请注意它附带了一个 web 字体预设 以方便加载 来自常见提供商的字体,包括 Google Fonts 等。

Advanced

过渡

Nuxt 带有与 Vue 相同的 <Transition> 元素,并且还支持实验性的 View Transitions API

字体高级优化

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

始终记住充分利用整个 Web 生态系统中可用的各种工具和技术,使您的应用程序的样式设计变得更容易、更高效。 无论您使用的是原生 CSS、预处理器、postcss、UI 库还是模块,Nuxt 都能满足您的需求。 快乐造型!

LCP 高级优化

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

  • 使用 CDN,使文件在物理上更接近您的用户
  • 压缩你的资源,最好使用 Brotli
  • 使用HTTP2/HTTP3进行传送
  • 在同一域上托管您的资产(不要使用不同的子域)

如果您使用的是 Cloudflare、Netlify 或 Vercel 等现代平台,那么大多数事情都应该自动为您完成。 您可以在 web.dev 上找到 LCP 优化指南。

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

nuxt.config.ts
ts
export default defineNuxtConfig({
  hooks: {
    'build:manifest': (manifest) => {
      // 找到app入口,css列表
      const css = manifest['node_modules/nuxt/dist/app/entry.js']?.css
      if (css) {
        // 从数组末尾开始并转到开头
        for (let i = css.length - 1; i >= 0; i--) {
          // 如果它以“entry”开头,则将其从列表中删除
          if (css[i].startsWith('entry'))
            css.splice(i, 1)
        }
      }
    },
  },
})