样式
Nuxt在样式处理方面具有高度灵活性。你可以编写自己的样式,或引用本地和外部样式表。 可以使用CSS预处理器、CSS框架、UI库和Nuxt模块来为应用添加样式。
本地样式表
如果要编写本地样式表,最合适的位置是assets/
目录。
在组件中导入
你可以直接在页面、布局和组件中导入样式表。
可以使用JavaScript导入,或CSS的@import
语句。
<script>
// 使用静态导入以确保服务端兼容性
import '~/assets/css/first.css'
// 注意:动态导入不兼容服务端
import('~/assets/css/first.css')
</script>
<style>
@import url("~/assets/css/second.css");
</style>
CSS配置项
你也可以在Nuxt配置中使用css
属性。
样式表最合适的位置是assets/
目录。然后引用其路径,Nuxt会将其包含到应用的所有页面中。
export default defineNuxtConfig({
css: ['~/assets/css/main.css']
})
使用字体
将本地字体文件放在~/public/
目录下,例如~/public/fonts
。然后可以在样式表中使用url()
引用它们。
@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
yarn add animate.css
pnpm install animate.css
bun install animate.css
然后你可以直接在页面、布局和组件中引用它:
<script>
import 'animate.css'
</script>
<style>
@import url("animate.css");
</style>
也可以在Nuxt配置的css属性中以字符串形式引用这个包。
export default defineNuxtConfig({
css: ['animate.css']
})
外部样式表
你可以通过在nuxt配置文件的head部分添加link元素来包含外部样式表。可以通过不同方法实现这一效果。注意本地样式表也可以通过这种方式包含。
你可以使用Nuxt配置的app.head
属性来操作head:
export default defineNuxtConfig({
app: {
head: {
link: [{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css' }]
}
}
})
动态添加样式表
你可以使用useHead组合式API在代码中动态设置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
中创建一个插件:
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
npm install -D less
npm install -D stylus
编写样式表最合适的位置是assets
目录。
然后可以在app.vue
(或布局文件)中使用预处理器的语法导入源文件。
<style lang="scss">
@use "~/assets/scss/main.scss";
</style>
或者,你也可以使用Nuxt配置的css
属性。
export default defineNuxtConfig({
css: ['~/assets/scss/main.scss']
})
如果需要在预处理文件中注入代码,比如带有颜色变量的Sass局部文件,可以使用Vite的预处理器选项。
在assets
目录中创建一些局部文件:
$primary: #49240F;
$secondary: #E4A79D;
$primary: #49240F
$secondary: #E4A79D
然后在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,请参考每个预处理器加载器的文档。
预处理器工作线程(实验性)
Vite提供了一个实验性选项,可以加速预处理器的使用。
你可以在nuxt.config
中启用它:
export default defineNuxtConfig({
vite: {
css: {
preprocessorMaxWorkers: true // CPU数量减1
}
}
})
单文件组件(SFC)样式
Vue和SFC最棒的一点是它天然擅长处理样式。你可以直接在组件文件的style块中编写CSS或预处理器代码,因此你将获得出色的开发体验,而无需使用CSS-in-JS之类的东西。但是,如果你想使用CSS-in-JS,可以找到支持它的第三方库和模块,例如pinceau。
你可以参考Vue文档获取关于在SFC中为组件添加样式的全面参考。
类和样式绑定
你可以利用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>
<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文档获取更多信息。
v-bind
的动态样式 使用
你可以使用v-bind函数在style块中引用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属性允许你以隔离的方式为组件添加样式。使用此属性声明的样式仅适用于此组件。
<template>
<div class="example">hi</div>
</template>
<style scoped>
.example {
color: red;
}
</style>
CSS模块
你可以使用CSS模块和module属性。通过注入的$style
变量访问它。
<template>
<p :class="$style.red">This should be red</p>
</template>
<style module>
.red {
color: red;
}
</style>
预处理器支持
SFC的style块支持预处理器语法。Vite内置支持.scss、.sass、.less、.styl和.stylus文件,无需配置。你只需要先安装它们,它们就可以直接在SFC中使用lang属性。
<style lang="scss">
/* 在这里编写scss */
</style>
<style lang="sass">
/* 在这里编写sass */
</style>
<style lang="less">
/* 在这里编写less */
</style>
<style lang="stylus">
/* 在这里编写stylus */
</style>
你可以参考Vite CSS文档和@vitejs/plugin-vue文档。 对于webpack用户,请参考vue loader文档。
使用PostCSS
Nuxt内置了postcss。你可以在nuxt.config
文件中配置它。
export default defineNuxtConfig({
postcss: {
plugins: {
'postcss-nested': {},
'postcss-custom-media': {}
}
}
})
为了在SFC中获得正确的语法高亮,你可以使用postcss的lang属性。
<style lang="postcss">
/* 在这里编写postcss */
</style>
默认情况下,Nuxt已经预配置了以下插件:
- postcss-import:改进
@import
规则 - postcss-url:转换
url()
语句 - autoprefixer:自动添加供应商前缀
- cssnano:压缩和清除
利用布局实现多种样式
如果你需要为应用的不同部分完全不同的样式,可以使用布局。 为不同的布局使用不同的样式。
<template>
<div class="default-layout">
<h1>Default Layout</h1>
<slot />
</div>
</template>
<style>
.default-layout {
color: red;
}
</style>
第三方库和模块
Nuxt在样式方面没有强制意见,并为你提供了多种选择。你可以使用任何你想要的样式工具,例如流行的库如UnoCSS或Tailwind CSS。
社区和Nuxt团队开发了许多Nuxt模块以使集成更容易。 你可以在网站的模块部分发现它们。 以下是一些帮助你入门的模块:
- UnoCSS:即时按需原子CSS引擎
- Tailwind CSS:实用优先的CSS框架
- Fontaine:字体度量回退
- Pinceau:适应性样式框架
- Nuxt UI:现代Web应用的UI库
- Panda CSS:在构建时生成原子CSS的CSS-in-JS引擎
Nuxt模块为你提供了开箱即用的良好开发体验,但请记住,如果你最喜欢的工具没有模块,并不意味着你不能在Nuxt中使用它!你可以为自己的项目自行配置。根据工具的不同,你可能需要使用Nuxt插件和/或创建自己的模块。如果你这样做了,请与社区分享!
轻松加载Web字体
你可以使用Nuxt Google Fonts模块来加载Google字体。
如果你使用UnoCSS,请注意它附带了一个web字体预设,可以方便地从常见提供商(包括Google字体等)加载字体。
高级
过渡效果
Nuxt带有与Vue相同的<Transition>
元素,并且还支持实验性的视图过渡API。
字体高级优化
我们推荐使用Fontaine来减少你的CLS。如果需要更高级的功能,考虑创建一个Nuxt模块来扩展构建过程或Nuxt运行时。
LCP高级优化
你可以执行以下操作来加速全局CSS文件的下载:
- 使用CDN,使文件物理上更接近你的用户
- 压缩你的资源,最好使用Brotli
- 使用HTTP2/HTTP3进行交付
- 将资源托管在同一域名下(不要使用不同的子域名)
如果你使用现代平台如Cloudflare、Netlify或Vercel,大多数这些操作应该会自动完成。 你可以在web.dev上找到LCP优化指南。
如果你的所有CSS都被Nuxt内联,你可以(实验性地)完全停止在渲染的HTML中引用外部CSS文件。 你可以通过一个钩子来实现这一点,你可以将其放在模块中或Nuxt配置文件中。
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'开头,从列表中移除
if (css[i].startsWith('entry')) css.splice(i, 1)
}
}
},
},
})