文章目录
写 CSS 看起来简单,但项目大了问题就来了:类名冲突、样式覆盖、主题切换......Nuxt 提供了多种样式管理方案,今天我们来梳理一下最佳实践。
一、全局样式
全局样式放在 assets 或 css 目录,在 nuxt.config.ts 中引入:
ts
export default defineNuxtConfig({
css: [
'~/assets/css/main.css',
'~/assets/css/reset.css'
]
})
创建 assets/css/main.css:
css
/* 全局变量 */
:root {
--primary-color: #00dc82;
--text-color: #333;
--bg-color: #fff;
--border-radius: 4px;
}
/* 暗色主题 */
.dark {
--primary-color: #00b36b;
--text-color: #fff;
--bg-color: #1a1a1a;
}
/* 全局基础样式 */
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
color: var(--text-color);
background-color: var(--bg-color);
line-height: 1.6;
}
a {
color: var(--primary-color);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
二、CSS 变量与主题切换
CSS 变量让主题切换变得简单:
vue
<script setup lang="ts">
const isDark = ref(false)
const toggleTheme = () => {
isDark.value = !isDark.value
document.documentElement.classList.toggle('dark', isDark.value)
}
// 初始化时检查系统主题
onMounted(() => {
isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches
document.documentElement.classList.toggle('dark', isDark.value)
})
</script>
<template>
<button @click="toggleTheme">
{{ isDark ? '🌙' : '☀️' }}
</button>
</template>
配合 @nuxtjs/color-mode 模块更方便:
bash
pnpm add @nuxtjs/color-mode
ts
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/color-mode']
})
vue
<script setup lang="ts">
const colorMode = useColorMode()
const toggleTheme = () => {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
}
</script>
<template>
<button @click="toggleTheme">
{{ colorMode.value === 'dark' ? '🌙' : '☀️' }}
</button>
</template>
三、Scoped CSS
组件内的样式使用 scoped 避免污染:
vue
<template>
<div class="card">
<h2 class="title">标题</h2>
<p class="content">内容</p>
</div>
</template>
<style scoped>
.card {
border: 1px solid #eee;
border-radius: var(--border-radius);
padding: 1rem;
}
.title {
color: var(--primary-color);
margin-bottom: 0.5rem;
}
.content {
color: var(--text-color);
}
</style>
scoped 会给样式加上唯一的属性选择器,不会影响其他组件。
四、CSS Modules
想要更严格的类名隔离,用 CSS Modules:
vue
<script setup lang="ts">
import styles from './ArticleCard.module.css'
</script>
<template>
<article :class="styles.card">
<h2 :class="styles.title">文章标题</h2>
<p :class="styles.content">文章内容</p>
</article>
</template>
ArticleCard.module.css:
css
.card {
border: 1px solid #eee;
padding: 1rem;
}
.title {
color: #333;
}
.content {
color: #666;
}
编译后类名会变成 _card_abc123 这样的唯一值。
五、Tailwind CSS
Nuxt 对 Tailwind 支持很好:
bash
pnpm add -D @nuxtjs/tailwindcss
ts
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxtjs/tailwindcss'],
tailwindcss: {
cssPath: '~/assets/css/tailwind.css',
configPath: 'tailwind.config.ts'
}
})
创建 tailwind.config.ts:
ts
import type { Config } from 'tailwindcss'
export default {
content: [
'./components/**/*.{js,vue,ts}',
'./layouts/**/*.vue',
'./pages/**/*.vue',
'./plugins/**/*.{js,ts}',
'./app.vue'
],
theme: {
extend: {
colors: {
primary: '#00dc82'
}
}
}
} satisfies Config
现在可以直接用 Tailwind 类名:
vue
<template>
<div class="p-4 border rounded-lg">
<h1 class="text-2xl font-bold text-primary">标题</h1>
<p class="text-gray-600 mt-2">内容</p>
<button class="mt-4 px-4 py-2 bg-primary text-white rounded hover:opacity-80">
按钮
</button>
</div>
</template>
六、UnoCSS
UnoCSS 是原子化 CSS 引擎,比 Tailwind 更快:
bash
pnpm add -D @unocss/nuxt
ts
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@unocss/nuxt']
})
创建 uno.config.ts:
ts
import { defineConfig, presetUno, presetAttributify, presetIcons } from 'unocss'
export default defineConfig({
presets: [
presetUno(),
presetAttributify(),
presetIcons()
]
})
使用方式和 Tailwind 类似:
vue
<template>
<div p-4 border rounded-lg>
<h1 text-2xl font-bold text-primary>标题</h1>
<button mt-4 px-4 py-2 bg-primary text-white rounded hover:opacity-80>
按钮
</button>
</div>
</template>
七、预处理器支持
Nuxt 支持 Sass、Less、Stylus 等预处理器:
bash
pnpm add -D sass
使用:
vue
<style scoped lang="scss">
$primary: #00dc82;
.card {
border: 1px solid #eee;
.title {
color: $primary;
&:hover {
opacity: 0.8;
}
}
.content {
color: #666;
}
}
</style>
全局 Sass 变量,创建 assets/css/variables.scss:
scss
$primary: #00dc82;
$text-color: #333;
在 nuxt.config.ts 配置:
ts
export default defineNuxtConfig({
vite: {
css: {
preprocessorOptions: {
scss: {
additionalData: '@use "~/assets/css/variables.scss" as *;'
}
}
}
}
})
现在所有组件都能直接用这些变量:
vue
<style scoped lang="scss">
.title {
color: $primary; // 直接使用,无需 import
}
</style>
八、PostCSS 配置
Nuxt 内置了 PostCSS,可以添加插件:
ts
// nuxt.config.ts
export default defineNuxtConfig({
postcss: {
plugins: {
'postcss-nested': {}, // 支持嵌套
'autoprefixer': {} // 自动添加前缀(默认已开启)
}
}
})
九、动态样式
根据状态动态改变样式:
vue
<script setup lang="ts">
const theme = ref({
primary: '#00dc82',
fontSize: '14px'
})
const styleVars = computed(() => ({
'--primary': theme.value.primary,
'--font-size': theme.value.fontSize
}))
</script>
<template>
<div :style="styleVars" class="container">
<p class="text">这段文字会根据主题变化</p>
<button @click="theme.primary = '#ff0000'">换成红色</button>
</div>
</template>
<style scoped>
.text {
color: var(--primary);
font-size: var(--font-size);
}
</style>
总结
样式管理方案对比:
| 方案 | 特点 | 适用场景 |
|---|---|---|
| 全局 CSS | 简单直接 | 基础样式、变量 |
| Scoped CSS | Vue 原生支持 | 组件内部样式 |
| CSS Modules | 类名隔离严格 | 大型项目 |
| Tailwind/UnoCSS | 原子化、快速 | 快速开发 |
| Sass/Less | 变量、嵌套 | 复杂样式需求 |
推荐组合:全局 CSS 变量 + Scoped CSS + Tailwind(可选)
下一篇聊聊静态资源管理,让你的图片、字体管理更规范。
相关文章
延伸阅读
内容有帮助?点赞、收藏、关注三连!评论区等你 💪