iT邦幫忙

2025 iThome 鐵人賽

DAY 6
0
自我挑戰組

你努力一下啦,自己做一個前端專案啦系列 第 6

<你努力一下啦,自己做一個前端專案啦!06>:上班偷偷玩,用個"看起來"專業的主題顏色

  • 分享至 

  • xImage
  •  

了解 :root 與 @theme 的使用方式

:root

:root指的是整個文件的根元素——在一般網頁就是 <html>。不過 :root 和 html 選擇器不完全等價,最大差異在權重(specificity) 與一些進階用法。

  • :root 代表文件(或 Shadow DOM)樹的根。
  • 權重::root 是偽類(0,1,0),比 html(元素選擇器 0,0,1)更高,因此更不易被覆蓋。
  • 最常用來放全域 CSS 變數(custom properties) 與主題(theme) token。

用途

  1. 全域設計變數(色票、字體、間距…)
:root {
  --brand: oklch(0.72 0.15 250);
  --radius-lg: 1rem;
  --font-sans: Inter, ui-sans-serif, system-ui, sans-serif;
}

.button {
  background: var(--brand);
  border-radius: var(--radius-lg);
  font-family: var(--font-sans);
}
  1. 主題切換(light / dark / brand)
    把可變的值放在 :root,切換時改變根上的屬性或 class:
:root { --bg: white; --fg: #111; }
html[data-theme="dark"] { --bg: #111; --fg: #eee; }

body { background: var(--bg); color: var(--fg); }

也可以寫 :root[data-theme="dark"] {...},效果等同於 html[data-theme="dark"],但權重較高。

  1. 全域行為或預設
:root {
  color-scheme: light dark;   /* 讓瀏覽器表單/卷軸自動配合深淺色 */
  scroll-behavior: smooth;    /* 全站平滑捲動 */
  font-size: 16px;            /* 全站字級基準(會影響 rem) */
}

注意事項

只是標準 CSS 變數的宣告點,讓整站可用 var(--token) 取值;它不會讓 Tailwind 生成任何 utility/variant。適合放「不需要對應成 Tailwind 類別」的應用層變數(例如品牌色、主題開關值)。

@theme

在 v4,Tailwind 以 CSS 變數(design tokens)驅動大多數工具類別。你在 CSS 裡用 @theme 定義/覆寫這些變數,Tailwind 就會依此自動產生相對應的 utility/variant(例如顏色、字體、斷點等)。

用途

延伸、覆寫、或重置預設主題

  1. 延伸(新增)
@theme { --font-script: "Great Vibes", cursive; } /* 新增 .font-script */
  1. 覆寫(改掉單一預設值)
@theme { --breakpoint-sm: 30rem; } /* 改變 sm 觸發點 */
  1. 重置某一整個命名空間
    將該命名空間清空後只保留我們定義的值(例如只用自家色票):
@theme {
  --color-*: initial;     /* 先清空預設色票 */
  --color-brand: #4f46e5; /* 之後只會有 .bg-brand 等 */
}
  1. 完全不用預設主題
@theme {
  --*: initial;                  /* 清空全部預設 token */
  --spacing: 4px;
  --font-body: Inter, sans-serif;
  --color-lagoon: oklch(0.72 0.11 221.19);
}

實作:遊戲專案的主題色彩

為了看起來專業(也能偷偷在上班玩 ),我們定義了一組色票與動畫效果。:

/* src/style.css */
@import "tailwindcss";

@theme {
  /* 主色系 - 平靜藍 */
  --color-primary-50: #f0f9ff;
  --color-primary-100: #e0f2fe;
  --color-primary-200: #bae6fd;
  --color-primary-300: #7dd3fc;
  --color-primary-400: #38bdf8;
  --color-primary-500: #0ea5e9;  /* 主要藍色 */
  --color-primary-600: #0284c7;
  --color-primary-700: #0369a1;
  --color-primary-800: #075985;
  --color-primary-900: #0c4a6e;

  /* 遊戲功能色彩 */
  --color-health: #ef4444;      /* 血量紅 */
  --color-experience: #22c55e;  /* 經驗綠 */
  --color-mana: #3b82f6;        /* 魔力藍 */
  --color-explore: #10b981;     /* 探索翠綠 */

  /* 物品稀有度 */
  --color-rarity-common: #64748b;    /* 普通 */
  --color-rarity-rare: #3b82f6;      /* 稀有 */
  --color-rarity-epic: #8b5cf6;      /* 史詩 */
  --color-rarity-legendary: #f59e0b;  /* 傳說 */

  /* 動畫定義 */
  --animate-progress: progress 0.5s ease-out;
  --animate-glow: glow 2s ease-in-out infinite alternate;
}

/* 自訂動畫 */
@keyframes progress {
  0% { width: 0%; }
  100% { width: var(--progress-width); }
}

@keyframes glow {
  0% { box-shadow: 0 0 5px rgba(59, 130, 246, 0.5); }
  100% { box-shadow: 0 0 20px rgba(59, 130, 246, 0.8); }
}

/* 進度條漸變效果 */
:root {
  --gradient-health: linear-gradient(90deg, #ef4444 0%, #dc2626 100%);
  --gradient-experience: linear-gradient(90deg, #22c55e 0%, #16a34a 100%);
  --gradient-explore: linear-gradient(90deg, #10b981 0%, #059669 100%);
}

@layer components {
  /* 進度條組件 */
  .progress-health {
    background: var(--gradient-health);
    @apply h-full rounded-full transition-all duration-300;
  }

  .progress-experience {
    background: var(--gradient-experience);
    @apply h-full rounded-full transition-all duration-300;
  }

  .progress-explore {
    background: var(--gradient-explore);
    @apply h-full rounded-full transition-all duration-500;
  }

  /* 物品稀有度效果 */
  .item-rare {
    @apply border-rarity-rare text-rarity-rare;
    box-shadow: 0 0 10px rgba(59, 130, 246, 0.3);
  }

  .item-epic {
    @apply border-rarity-epic text-rarity-epic;
    box-shadow: 0 0 15px rgba(139, 92, 246, 0.3);
  }

  .item-legendary {
    @apply border-rarity-legendary text-rarity-legendary;
    box-shadow: 0 0 20px rgba(245, 158, 11, 0.3);
    animation: var(--animate-glow);
  }
}

/* 基礎樣式 */
body {
  font-family: 'Inter', system-ui, sans-serif;
  @apply text-gray-700 bg-gradient-to-br from-primary-50 to-primary-100;
}

結語

這次整理了 :root 和 @theme 的使用方式,實際玩了一下顏色與動畫設定。
:root 比較像是 全域 CSS 變數的倉庫,方便管理品牌色或主題切換;
而 @theme 則能直接影響 Tailwind 的設計 token,讓 utility 類別自動跟著更新。

把兩者結合起來,就能在專案裡建立一套屬於自己的設計系統,
同時享受 Tailwind 的便利 和 CSS 變數的彈性。

接下來,就可以開始把這些設計 token 實際用在 UI 元件上,
讓「遊戲」慢慢成形。

專案連結


上一篇
<你努力一下啦,自己做一個前端專案啦!05>:手機先玩!Mobile first design
下一篇
<你努力一下啦,自己做一個前端專案啦!07>:用個進度條看起來很專業
系列文
你努力一下啦,自己做一個前端專案啦8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言