Vue3 – 全域樣式(Global Styles)完整指南
簡介
在單頁應用(SPA)中,樣式的管理往往是最容易失控的部分。隨著元件數量增加,若每個元件都自行定義自己的 CSS,最終會出現樣式衝突、重複宣告、甚至無法預測的渲染結果。Vue3 提供了多種方式來統一或局部管理樣式,而 全域樣式(global styles) 則是最基礎、最常用的手段之一。
全域樣式的目的在於:
- 為整個應用提供一致的基礎排版、色彩、字型等「全站」設定。
- 定義可重複使用的工具類別(utility classes)或 CSS 變數,讓各個元件只需引用即可。
- 減少重複的 CSS,提升載入效能與維護性。
本篇文章將從概念說明、實作範例、常見陷阱與最佳實踐,帶你一步步掌握在 Vue3 中如何正確使用全域樣式,並提供實務應用情境,幫助你在專案中快速落地。
核心概念
1. 為什麼要使用全域樣式?
- 一致性:全站的字型、行高、顏色等設計規則在一處設定,所有元件自動遵守。
- 可維護性:當品牌顏色或排版規則需要調整時,只要改一個地方即可。
- 工具類別:像是
text-center、mt-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.js 或 App.vue。 |
| 缺乏變數 | 直接寫死顏色或尺寸,後期改版成本高。 | 使用 CSS Custom Properties(變數)或 Sass 變數,配合主題切換。 |
| 開發環境與生產環境差異 | 有時在開發時使用 :root 變數,生產環境卻因壓縮失效。 |
確認 Vite/webpack 的 CSS 壓縮 不會移除未使用的變數,必要時在 postcss 加入 preserve 設定。 |
| 樣式載入順序 | 全域樣式若在局部樣式之後載入,會被局部樣式覆寫。 | 利用 import 順序 或 @layer(CSS Layers)控制優先級。 |
最佳實踐
分層管理:
reset.css/normalize.css→ 基礎瀏覽器重置variables.css→ 顏色、字型、間距變數global.css→ 基礎排版、工具類別theme.css→ 顏色主題、暗黑模式
使用 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); }結合 PostCSS
postcss-preset-env:讓舊瀏覽器也能支援變數與@layer。主題切換:在 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 應用中不可或缺的基礎建設,它提供了設計一致性、變數化管理與快速開發的便利。掌握以下幾點,即可在專案中安全、有效地使用全域樣式:
- 選擇合適的匯入方式(
main.js、App.vue、預處理器)並保持唯一入口。 - 使用 CSS Custom Properties 或 Sass 變數,確保未來主題或品牌調整成本最低。
- 避免樣式污染:僅將真正全域的基礎樣式放在全域檔,其他則採用
scoped、BEM 或 CSS Modules。 - 結合工具類別與設計系統,讓開發者能在模板中直接使用
mt-4、text-center等類別,提升開發效率。 - 留意載入順序與層級,透過
@layer或 import 順序控制樣式優先級,避免意外覆寫。
只要遵循以上最佳實踐,你就能在 Vue3 專案裡 構建乾淨、可維護且具彈性 的全域樣式體系,為後續的功能開發與 UI 升級奠定堅實基礎。祝開發順利,寫出美觀又穩定的 Vue3 應用! 🚀