昨天講交付時提過一句:token 是設計與工程之間的單一真實來源,而 Code Connect 讓這個來源在交付當下被強制引用。今天把鏡頭往這個來源本身推近——如果 token 真的是全公司設計決策的中樞,那它用什麼格式存、能不能同時餵給網頁、iOS、Android 而不各自失真,就是一個比「handoff 流程」更底層的問題。這件事在 2025 年 10 月 28 日有了分水嶺:Design Tokens Community Group 發布了 W3C Design Tokens 格式的第一個穩定版(2025.10)。design token 從各家工具各說各話,第一次有了一份中立、可攜、production-ready 的共同語言。

📖 學

為什麼要有一個「跨工具」的 token 格式

先把問題講清楚。過去三年,幾乎每個像樣的設計系統都在用 design token:把 #2563EB 這種裸值抽象成 color/action/primary 這種有語意的名字,再讓程式碼去引用名字而不是值。這個抽象本身沒問題,問題出在每個工具存 token 的檔案格式都不一樣。Figma 的 variables 匯出是一種結構、Style Dictionary 吃的是另一種、Tokens Studio 又是一種、native 端的 Swift/XML 各是各的。結果就是你以為有了「單一真實來源」,實際上維護的是一堆需要互相翻譯的方言,每接一個新工具就多一層轉換膠水,而膠水正是最容易漏東西的地方。

W3C DTCG 格式要解的就是這件事:它不是又一個工具,而是一份中立的交換格式(interchange format)。約定 token 用 .tokens.json 副檔名、application/design-tokens+json 這個 media type,內部每個 token 用 $value$type$description 三個保留鍵來描述。當 Figma、Style Dictionary、Penpot 都能讀寫同一份 JSON,token 才第一次真的是「一份檔案、到處通用」,而不是「一份檔案、每處重譯」。這也是為什麼 2025.10 被稱為 first stable version 很重要:穩定版意味著工具廠商可以放心照著實作,不必擔心明天鍵名又改了。

這版穩下來的到底是什麼

穩定版最實際的三塊,值得逐一記住,因為它們直接對應你每天在設計系統裡會踩到的坑。

第一是複合型別(composite types)。過去 token 大多只能存單一純量——一個顏色、一個間距。但真實的設計屬性常常是好幾個值綁在一起才有意義:一個陰影是 offset、blur、spread、color 的組合;一段 typography 是 font family、size、weight、line-height、letter-spacing 的組合;border、gradient 也一樣。2025.10 為 shadow、gradient、border、typography 這些定義了固定結構的 composite type,讓「一個排版樣式」可以當成一個完整的 token 來傳,而不是拆成五個彼此無關的裸值,到了另一端再靠人記憶重新組回去。

第二是主題與多品牌(theming / multi-brand)。淺色/深色、無障礙的高對比變體、不同品牌線的配色,過去常見的做法是整份 token 檔複製一份再逐一改值,於是同一個決策散在三四個檔案裡,改一次要記得改到每一份。新格式支援在同一套結構下表達這些變體,避免檔案複製(without file duplication),讓「亮暗兩套」是同一棵樹上的分支,而不是兩棵要手動同步的樹。

第三是現代色彩空間。格式完整支援 Display P3、Oklch 以及 CSS Color Module 4 的各種色彩空間。這不是規格書上的裝飾:Oklch 的感知均勻特性讓你調整明度時色相不會漂移,做無障礙對比與程式化的色階(color ramp)時比 hex/HSL 可靠得多;而 P3 廣色域則是這幾年高階螢幕的既成事實。token 格式把這些寫進標準,等於承認「顏色」在 2026 年已經不只是六碼十六進位了。

搭上這些的還有 token 之間的關係:別名(alias)、繼承、以及元件層級的引用。也就是說 color/action/primary 可以指向 color/brand/blue-600,而按鈕元件的 token 又指向 color/action/primary——三層語意(原始值 → 語意 token → 元件 token)可以乾淨地表達在同一份可攜檔案裡。

從一份 JSON 長出三個平台:Style Dictionary 的角色

有了中立格式只完成一半。格式負責「存」,但每個平台要的長相不一樣:CSS 要 --color-action-primary 這種 kebab-case 的 custom property、Android 要 snake_case 的 XML resource、iOS Swift 要 PascalCase 的常數。把一份 .tokens.json 翻成這三種產物的,就是 build 工具,其中最主流的是 Style Dictionary。

Style Dictionary v4 已經把 DTCG 格式當成一等公民:直接指向一份 DTCG 檔,它會原生解析 $value$type$description,解開別名,再送進你設定的 transformer pipeline。你要做的是選對 name transform——name/kebab 產 CSS 變數、name/snake 產 Android resource、name/pascal 產 Swift/Objective-C 常數——同一份來源就能同時吐出 CSS、SCSS、iOS Swift、Android XML。這才是「跨平台一致性」真正的機械原理:不是三個平台各自維護一份看起來很像的值,而是三個平台編譯自同一份來源,值不可能不一致,因為它們根本是同一個數字經過不同命名規則印出來的。

把這條線接起來,一個成熟團隊 2026 年的 token 流水線長這樣:設計師在 Figma 重新指定一個語意 token → variables 匯出成 DTCG JSON → Style Dictionary 重新編譯 → 各平台在下一次 build 時自動吃到新值。一次改動,網頁與雙平台原生 App 同步更新,中間沒有任何人手動搬數字。這正好把昨天那條 handoff 流水線往上游延伸了一段:昨天談的是「一個畫面怎麼變成程式碼」,今天談的是「一個顏色決策怎麼一次同步到所有平台」。

一個務實的提醒:穩定 ≠ 全部就緒

別把「規格穩定」誤讀成「今天就能無痛全上」。現況是:2025.10 格式本身穩了,但工具端的完整支援還在追。Style Dictionary v4 支援的是較早的 DTCG 樣貌,對 2025.10 的完整相容要等 v5,目前仍在進行中(work in progress)。已宣布支援或正在實作這套標準的工具超過十個,包含 Penpot、Figma、Sketch、Framer、Knapsack、Supernova、zeroheight,但各家覆蓋的版本與細節不一。務實的姿態是:現在就用 DTCG 當你的權威來源格式(這步的報酬率最高、鎖定風險最低),但接每個工具前先確認它支援到哪個版本、哪些 composite type,把不支援的部分留在轉換層處理,而不是假設整條鏈都已對齊 2025.10。

🧠 記

  • 問題不是沒有 token,是每個工具的 token 格式都不同,於是「單一真實來源」實際上是一堆要互相翻譯的方言,膠水層最會漏東西。
  • W3C DTCG 2025.10(2025-10-28 首個穩定版) 是中立交換格式,不是工具:.tokens.jsonapplication/design-tokens+json,每個 token 用 $value / $type / $description 描述。
  • 這版穩下來的三大重點:composite types(shadow / gradient / border / typography 一次綁成一個 token)、theming/multi-brand(亮暗與品牌變體不必複製檔案)、現代色彩(Display P3、Oklch、CSS Color 4)。
  • 跨平台一致性的機械原理:不是三平台各存一份很像的值,而是三平台編譯自同一份來源。Style Dictionary v4 原生吃 DTCG,靠 name/kebab(CSS)、name/snake(Android XML)、name/pascal(Swift)一源多吐。
  • 流水線:Figma 改語意 token → 匯出 DTCG → Style Dictionary 重編 → 各平台下次 build 自動更新
  • 穩定 ≠ 全部就緒:格式穩了,工具支援還在追(Style Dictionary 完整相容 2025.10 要等 v5)。現在就把 DTCG 當權威來源,但逐工具確認支援版本。

✍️ 實踐

挑你手上一個真的要跨平台(至少 web + 一個 native)的色彩或排版 token,做三件事:

  1. 把它寫成一份 .tokens.json$value$type$description 三個鍵,並刻意做出三層:一個原始值 token(如 color/brand/blue-600)、一個指向它的語意 token(如 color/action/primary,用別名)、一個元件 token(如 button/bg/default 指向語意層)。做完你會直觀感受到:改一個原始值,三層一起連動——這就是「單一真實來源」的手感。
  2. 用 Style Dictionary 編一次,看三個產物。 設定 name/kebabname/snakename/pascal,分別吐出 CSS custom property、Android XML、Swift 常數,把三份輸出並排看。確認同一個 token 在三處的值完全一致、只有命名慣例不同。若不一致,問題一定在轉換設定,而不在你手動漏改——這正是這套流程要消滅的錯誤類別。
  3. 挑一個 composite 屬性升級。 拿一段既有的排版樣式(font family / size / weight / line-height 綁一起),把它從四個散落的裸值改寫成一個 typography 型別的 composite token。體會「一個排版決策 = 一個 token」在維護上少掉多少同步負擔。

🔗 延伸學習

💬 問 AI

我的設計系統有一份權威 design token 檔,想遷移到 W3C DTCG 2025.10 格式,並用 Style Dictionary 一源產出 web(CSS custom properties)、iOS(Swift)、Android(XML)三平台。請幫我:
1. 用 $value / $type / $description 設計三層結構(原始值 → 語意 token → 元件 token),並示範用別名(alias)串起來的一小段 .tokens.json,含一個顏色與一個 typography composite token。
2. 給我一份對應的 Style Dictionary 設定,分別用 name/kebab、name/snake、name/pascal 產出上述三平台,並解釋每個 transform 選擇的理由。
3. 指出目前 Style Dictionary 對 2025.10 尚未完整支援之處,哪些能力要留在轉換層或等 v5,給我一個務實的分階段遷移順序。