样式
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.
<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>
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.
export default defineNuxtConfig({
css: ['~/assets/css/main.css']
})
使用字体
¥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()
.
@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
yarn add animate.css
pnpm install animate.css
bun install animate.css
然后你可以在页面、布局和组件中直接引用它:
¥Then you can reference it directly in your pages, layouts and components:
<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.
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:
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.
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:
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
npm install -D less
npm install -D stylus
编写样式表的自然存放位置是 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.
<style lang="scss">
@use "~/assets/scss/main.scss";
</style>
或者,你可以使用 Nuxt 配置中的 css
属性。
¥Alternatively, you can use the css
property of your Nuxt configuration.
export default defineNuxtConfig({
css: ['~/assets/scss/main.scss']
})
如果你需要在预处理文件中注入代码,例如带有颜色变量的 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;
$primary: #49240F
$secondary: #E4A79D
然后在你的 nuxt.config
中:
¥Then in your nuxt.config
:
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "~/assets/_colors.scss" as *;'
}
}
}
}
})
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
sass: {
additionalData: '@use "~/assets/_colors.sass" as *\n'
}
}
}
}
})
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
}
}
})
单文件组件 (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>
<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"></div>
</template>
<script setup lang="ts">
const isActive = ref(true)
const errorClass = ref('text-danger')
</script>
<template>
<div :class="[{ active: isActive }, errorClass]"></div>
</template>
<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>
<div :style="[baseStyles, overridingStyles]"></div>
<div :style="styleObject"></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>
<style lang="sass">
/* Write sass here */
</style>
<style lang="less">
/* Write less here */
</style>
<style lang="stylus">
/* Write stylus 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.
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:
- postcss-import:改进
@import
规则 - postcss-url:转换
url()
语句 - autoprefixer:自动添加供应商前缀
- cssnano:最小化和清除
利用布局实现多种样式
¥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>
第三方库和模块
¥Third Party Libraries And Modules
Nuxt 在样式方面没有有态度,并为你提供了多种选择。你可以使用任何你想要的样式工具,例如 UnoCSS 或 Tailwind 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:
- UnoCSS:即时按需原子 CSS 引擎
- Tailwind CSS:实用优先的 CSS 框架
- Fontaine:字体指标回退
- Pinceau:自适应样式框架
- Nuxt UI:适用于现代 Web 应用的 UI 库
- Panda CSS:CSS-in-JS 引擎,在构建时生成原子 CSS
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.
字体高级优化
¥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.
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.
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)
}
}
},
},
})