本文 AI 產出,尚未審核

Vue3 – 全域樣式(Global Styles)完整指南


簡介

在單頁應用(SPA)中,樣式的管理往往是最容易失控的部分。隨著元件數量增加,若每個元件都自行定義自己的 CSS,最終會出現樣式衝突、重複宣告、甚至無法預測的渲染結果。Vue3 提供了多種方式來統一或局部管理樣式,而 全域樣式(global styles) 則是最基礎、最常用的手段之一。

全域樣式的目的在於:

  1. 為整個應用提供一致的基礎排版、色彩、字型等「全站」設定。
  2. 定義可重複使用的工具類別(utility classes)或 CSS 變數,讓各個元件只需引用即可。
  3. 減少重複的 CSS,提升載入效能與維護性。

本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,帶你一步步掌握在 Vue3 中如何正確使用全域樣式,並提供實務應用情境,幫助你在專案中快速落地。


核心概念

1. 為什麼要使用全域樣式?

  • 一致性:全站的字型、行高、顏色等設計規則在一處設定,所有元件自動遵守。
  • 可維護性:當品牌顏色或排版規則需要調整時,只要改一個地方即可。
  • 工具類別:像是 text-centermt-4 這類的 utility class,讓開發者在模板中直接使用,減少自訂 CSS。

注意:全域樣式並非萬能,過度依賴會導致元件耦合度提升,失去 Vue 元件化的好處。因此,適度使用、與局部樣式(scoped)相輔相成是最佳策略。

2. Vue3 中加入全域樣式的三種常見方式

方式 說明 適用情境
main.js/main.ts 中匯入 CSS 檔 直接 import './assets/css/global.css',Webpack/Vite 會將其視為全域樣式。 小型專案或快速驗證,無需額外設定。
App.vue 中使用 <style>(不加 scoped 把全域 CSS 放在根元件的 <style> 區塊,會自動套用到子樹。 想把全域樣式與根元件放在同一檔案,方便管理。
使用 CSS Modules、PostCSS、Sass 等預處理器 透過 Vite 或 Vue CLI 的設定,將全域變數、混入(mixin)等抽離成獨立檔案。 大型專案需要變數、主題切換、或與設計系統整合。

以下分別示範這三種方式的 實作範例,並說明每個步驟的重點。


程式碼範例

範例 1:在 main.js 中匯入全域 CSS

// src/main.js
import { createApp } from 'vue'
import App from './App.vue'

// 1️⃣ 匯入全域樣式檔案
import '@/assets/css/global.css'   // 這裡使用別名 @ 指向 src

createApp(App).mount('#app')
/* src/assets/css/global.css */

/* 基本排版 */
html, body {
  margin: 0;
  padding: 0;
  font-family: 'Noto Sans TC', sans-serif;
  line-height: 1.6;
}

/* 文字顏色與背景 */
body {
  background-color: #f9fafb;
  color: #2d3748;
}

/* 常用工具類別 */
.text-center { text-align: center; }
.mt-4 { margin-top: 1rem; }

重點:只要在入口檔案匯入一次,整個 Vue 應用的所有元件都會自動套用這些樣式。


範例 2:在 App.vue 中直接寫全域 <style>

<!-- src/App.vue -->
<template>
  <router-view />
</template>

<script setup>
  // 這裡不需要額外程式碼
</script>

<style>
/* 2️⃣ 這裡的樣式會被視為全域,無 scoped 限制 */
:root {
  --primary-color: #3b82f6;
  --font-base: 'Noto Sans TC', sans-serif;
}

/* 全域排版 */
* {
  box-sizing: border-box;
  font-family: var(--font-base);
}

/* 設計系統的按鈕樣式 */
.btn-primary {
  display: inline-block;
  padding: 0.5rem 1rem;
  background-color: var(--primary-color);
  color: #fff;
  border: none;
  border-radius: 0.25rem;
  cursor: pointer;
}
</style>

提示:若你同時在子元件使用 scoped,根元件的全域樣式仍會優先套用,避免不必要的樣式衝突。


範例 3:使用 Sass 變數與 mixin,打造可主題化的全域樣式

/* src/assets/scss/_variables.scss */
$primary: #3b82f6;
$secondary: #10b981;
$font-base: 'Noto Sans TC', sans-serif;

/* 文字尺寸 */
$font-size-base: 1rem;
$font-size-lg: 1.25rem;
/* src/assets/scss/_mixins.scss */
@mixin flex-center {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* src/assets/scss/global.scss */
@use 'variables' as *;
@use 'mixins' as *;

:root {
  --primary: #{$primary};
  --secondary: #{$secondary};
  --font-base: #{$font-base};
}

/* 全域排版 */
html, body {
  margin: 0;
  padding: 0;
  font-family: var(--font-base);
  font-size: $font-size-base;
  background-color: #f9fafb;
}

/* 工具類別 */
.text-center { text-align: center; }
.mt-4 { margin-top: 1rem; }

/* 以 mixin 建立常用 flex 置中 */
.flex-center { @include flex-center; }
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'

// 3️⃣ 匯入 Sass 編譯後的 CSS
import '@/assets/scss/global.scss'

createApp(App).mount('#app')

說明:透過 Sass 的變數與 mixin,全域樣式不僅可讀性更佳,未來若要改成暗黑模式,只需要在變數檔裡調整顏色即可,所有引用的元件會自動更新。


範例 4:使用 Vite 的 css.preprocessorOptions 讓全域變數自動注入

// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  css: {
    preprocessorOptions: {
      scss: {
        // 將變數檔自動注入每個 SCSS 檔案
        additionalData: `@import "@/assets/scss/_variables.scss";`
      }
    }
  }
})

好處:開發者在任何 .vue 中使用 SCSS 時,都可以直接使用 $primary$font-base 等變數,省去每次手動 @import


範例 5:結合 CSS Modules 作為全域 utility

<!-- src/components/BaseButton.vue -->
<template>
  <button :class="[styles.btn, $style['btn-primary']]">
    <slot />
  </button>
</template>

<script setup>
import styles from '@/styles/utilities.module.css' // 全域 utility
</script>

<style module>
/* 這裡仍是局部作用域 */
.btn-primary {
  background-color: var(--primary);
  color: #fff;
}
</style>
/* src/styles/utilities.module.css */
.mt-2 { margin-top: 0.5rem; }
.px-4 { padding-left: 1rem; padding-right: 1rem; }

說明:利用 CSS Modules 的 module 特性,將全域的工具類別封裝成可在元件中直接 import,兼具 命名衝突避免全域可重用 的優點。


常見陷阱與最佳實踐

陷阱 說明 解決方案
樣式污染 全域 CSS 會影響所有子元件,若未妥善命名會造成意外覆寫。 使用 BEM 命名或 CSS Modules 只保留 truly global 的基礎樣式。
重複載入 同一檔案在多個入口(如 main.js + App.vue)匯入,會產生冗餘。 確保全域樣式只在 一處 匯入,建議統一放在 main.jsApp.vue
缺乏變數 直接寫死顏色或尺寸,後期改版成本高。 使用 CSS Custom Properties(變數)或 Sass 變數,配合主題切換。
開發環境與生產環境差異 有時在開發時使用 :root 變數,生產環境卻因壓縮失效。 確認 Vite/webpack 的 CSS 壓縮 不會移除未使用的變數,必要時在 postcss 加入 preserve 設定。
樣式載入順序 全域樣式若在局部樣式之後載入,會被局部樣式覆寫。 利用 import 順序@layer(CSS Layers)控制優先級。

最佳實踐

  1. 分層管理

    • reset.css / normalize.css → 基礎瀏覽器重置
    • variables.css → 顏色、字型、間距變數
    • global.css → 基礎排版、工具類別
    • theme.css → 顏色主題、暗黑模式
  2. 使用 CSS Custom Properties

    :root {
      --color-primary: #3b82f6;
      --color-primary-dark: #1e40af;
    }
    .btn-primary { background: var(--color-primary); }
    .dark .btn-primary { background: var(--color-primary-dark); }
    
  3. 結合 PostCSS postcss-preset-env:讓舊瀏覽器也能支援變數與 @layer

  4. 主題切換:在 Vue 中透過 provide/inject 或 Pinia 管理主題狀態,動態改變 data-theme 屬性,配合 CSS 變數完成即時切換。


實際應用場景

1. 企業內部系統的設計系統

大型企業往往有統一的 UI 規範(字型、顏色、間距)。透過 全域 CSS 變數 + SCSS mixin,在每個 Vue 元件只需要引用 var(--color-primary),即能保持一致且方便未來改版。

2. 多語系或暗黑模式切換

App.vue 中根據 Pinia 中的 theme 狀態切換 data-theme="dark",全域樣式利用 CSS 變數自動切換顏色:

<script setup>
import { useThemeStore } from '@/stores/theme'
const themeStore = useThemeStore()
</script>

<div :data-theme="themeStore.current">
  <router-view />
</div>
/* global.css */
:root {
  --bg-light: #ffffff;
  --bg-dark: #1a202c;
  --text-light: #2d3748;
  --text-dark: #e2e8f0;
}
[data-theme="dark"] {
  background-color: var(--bg-dark);
  color: var(--text-dark);
}
[data-theme="light"] {
  background-color: var(--bg-light);
  color: var(--text-light);
}

3. 第三方 UI 套件(如 Element Plus、Vuetify)與自定義樣式的混合

當使用 UI 套件時,套件本身會提供大量全域樣式。為避免衝突,自行定義的全域 CSS 應放在套件樣式之後,或利用 @layer 指定層級:

@layer base, components, utilities;

/* reset 於 base 層 */
@layer base {
  @import "reset.css";
}

/* 自訂工具類別於 utilities 層 */
@layer utilities {
  .mt-4 { margin-top: 1rem; }
}

總結

全域樣式是 Vue3 應用中不可或缺的基礎建設,它提供了設計一致性、變數化管理與快速開發的便利。掌握以下幾點,即可在專案中安全、有效地使用全域樣式:

  1. 選擇合適的匯入方式main.jsApp.vue、預處理器)並保持唯一入口。
  2. 使用 CSS Custom Properties 或 Sass 變數,確保未來主題或品牌調整成本最低。
  3. 避免樣式污染:僅將真正全域的基礎樣式放在全域檔,其他則採用 scoped、BEM 或 CSS Modules。
  4. 結合工具類別與設計系統,讓開發者能在模板中直接使用 mt-4text-center 等類別,提升開發效率。
  5. 留意載入順序與層級,透過 @layer 或 import 順序控制樣式優先級,避免意外覆寫。

只要遵循以上最佳實踐,你就能在 Vue3 專案裡 構建乾淨、可維護且具彈性 的全域樣式體系,為後續的功能開發與 UI 升級奠定堅實基礎。祝開發順利,寫出美觀又穩定的 Vue3 應用! 🚀