基础篇四 Nuxt4 全局样式与 CSS 模块

文章目录

写 CSS 看起来简单,但项目大了问题就来了:类名冲突、样式覆盖、主题切换......Nuxt 提供了多种样式管理方案,今天我们来梳理一下最佳实践。

一、全局样式

全局样式放在 assetscss 目录,在 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(可选)

下一篇聊聊静态资源管理,让你的图片、字体管理更规范。

相关文章

入门篇三:Nuxt4组件自动导入:写代码少敲一半字

入门篇二:Nuxt 4路由自动生成:告别手动配置路由的日子

延伸阅读

nuxt4完整系列,持续更新中。。,欢迎来逛逛


内容有帮助?点赞、收藏、关注三连!评论区等你 💪

相关推荐
云水一下16 小时前
HTML5 从入门到精通:实战收官——从零搭建完整静态网站,综合运用所有知识
前端·html5
不总是16 小时前
Windows 系统 Node.js 免安装版(zip)安装与配置教程(2026 最新)
前端·windows·node.js
冬奇Lab16 小时前
每日一个开源项目(第105篇):Twenty - 跳出 Salesforce 的圈套,定义现代开源 CRM
前端·后端·开源
zhangyao94033017 小时前
开发pc端时,表格的高度怎么设置才能铺满页面
前端·javascript·elementui
kjs--17 小时前
浏览器书签执行脚本
前端
烛衔溟17 小时前
TypeScript 类的类型 —— 作为类型使用
javascript·ubuntu·typescript
之歆18 小时前
Day16_JavaScript 轮播图与事件工程实战(下篇)
服务器·开发语言·前端·javascript·网络·性能优化
沄媪18 小时前
CSRF 跨站请求伪造
前端·ctf·csrf
kyriewen18 小时前
我关掉了Copilot:因为我写的代码出现在了别人的建议里
前端·javascript·ai编程