· Working ·
Design token là gì? Ba lớp raw, alias, semantic
Design token là một cặp tên và giá trị cho một quyết định thiết kế, dùng chung giữa Figma và code. Bài này giải thích ba lớp raw, alias, semantic, khác biệt với biến CSS, cách làm trong Figma Variables và Tailwind v4, kèm token thật của site này.
Design token là một cặp tên và giá trị lưu lại một quyết định thiết kế, ví dụ --muted-foreground bằng #595959. Component gọi token bằng tên, không gõ giá trị. Khi tổ chức token thành ba lớp raw, alias, semantic, bạn đổi màu thương hiệu hay thêm dark mode ở một chỗ mà không phải sửa từng component.
Tôi là Hai Le, UI/UX designer biết code. Site bạn đang đọc có hơn 160 biến màu chia đúng ba lớp trong file app/globals.css. Mọi ví dụ dưới đây chép từ file đó.
Design token là gì, nói đơn giản?
Đặc tả của W3C Design Tokens Community Group định nghĩa token là "thông tin gắn với một cái tên con người đọc được, tối thiểu là một cặp tên và giá trị". Ví dụ trong chính đặc tả: color-text-primary: #000000.
Định nghĩa đó đúng nhưng thiếu phần quan trọng. Cái tên mới là thứ có giá trị. #595959 chỉ là một mã màu. muted-foreground cho biết đây là màu chữ phụ, đứng sau chữ chính, và mọi chỗ cần chữ phụ đều phải dùng nó. Khi tôi đổi mã màu, cái tên vẫn giữ nguyên lời hứa đó.
Nói "design token" với hầu hết mọi người, thứ hiện ra trong đầu là một bảng mã hex. Bảng đó chỉ là phần dễ thấy nhất. Phần quyết định hệ thống có sống qua lần đổi thương hiệu đầu tiên hay không là cách bạn xếp các tên thành lớp.
Design token khác biến CSS ở đâu?
Biến CSS là cơ chế lưu trữ. Token là quy ước: giá trị này thuộc lớp nào, ai được gọi tới nó. Hai dự án cùng dùng biến CSS có thể một bên có hệ token thật, một bên chỉ có các hằng số đặt tên đẹp.
| Biến CSS | Design token | Figma Variable | |
|---|---|---|---|
| Là gì | Tính năng của CSS: --ten: giá-trị | Quy ước đặt tên và phân lớp cho quyết định thiết kế | Tính năng của Figma để lưu giá trị dùng lại |
| Sống ở đâu | File CSS, trình duyệt đọc | Bất kỳ đâu: CSS, JSON, Figma | File Figma |
| Trỏ tới nhau | var(--khac) | Tuỳ định dạng, ví dụ {brand.500} trong JSON | Aliasing, trỏ tới variable cùng kiểu |
| Đổi theo chế độ | Ghi đè trong selector, ví dụ .dark | Tuỳ công cụ | Mode trong collection |
Nói cách khác, biến CSS là một trong các chỗ token có thể sống. Ở site này, token sống trong biến CSS và được mô tả lại bằng chữ trong DESIGN.md.
Ba lớp token raw, alias, semantic là gì?
Lớp raw chỉ có giá trị. --gray-600 là #717171. Nó không biết mình sẽ thành chữ hay thành nền.
Lớp alias gắn vai trò cho cả một thang. --neutral-* là thang trung tính, --primary-* là thang thương hiệu, --error-* là thang báo lỗi. Đây vẫn là thang 11 bậc, nhưng đã có ý định.
Lớp semantic là thứ component chạm vào: --background, --foreground, --muted-foreground, --border, --primary. Tên của mỗi token nói nó dùng ở đâu. Màu cụ thể do lớp bên dưới quyết định.
Đây là ba dòng thật trong app/globals.css, nối một chuỗi từ giá trị tới component:
/* LỚP 0 — raw: chỉ có giá trị */
--gray-700: #595959;
/* LỚP 1 — alias: thang có vai trò */
--neutral-700: var(--gray-700);
/* LỚP 2 — semantic: component chạm vào đây */
--muted-foreground: var(--neutral-700);Và bảng vai trò của ba lớp trong site này:
| Lớp | Ví dụ | Ai được gọi | Đổi khi nào |
|---|---|---|---|
| Raw | --brand-500: #ff009d, --gray-700: #595959 | Chỉ lớp alias | Đổi thương hiệu, chỉnh tương phản |
| Alias | --primary-500, --neutral-700, --error-700 | Lớp semantic, đôi khi component | Hiếm khi |
| Semantic | --primary, --muted-foreground, --destructive | Component | Khi vai trò đổi, ví dụ nút lỗi đậm hơn |
Ở lớp semantic, tôi chỉ ghi var() trỏ về lớp alias, không ghi mã hex. Quy tắc đó được viết ngay đầu file CSS để người và AI sửa file đều thấy.
Vì sao không nên bỏ lớp alias ở giữa?
Bỏ lớp giữa, tức là để semantic trỏ thẳng về raw, nhìn có vẻ tiết kiệm. Vấn đề lộ ra vào lần đổi thương hiệu đầu tiên. Người ta phát hiện nửa codebase đang gõ thẳng giá trị raw ở những chỗ lẽ ra phải qua semantic, và không còn cách lần ngược lại ngoài tìm và thay bằng tay.
Lớp alias giải quyết chuyện đó bằng một lời hứa đơn giản: bậc số trong thang có nghĩa cố định. Ở site này, tôi đánh số thang trung tính theo quy ước của Radix. neutral-50 luôn là nền, neutral-950 luôn là chữ đậm nhất, ở cả chế độ sáng lẫn tối. Số bậc đo khoảng cách so với nền. Ở chế độ tối, neutral-950 là màu sáng nhất.
Nhờ vậy, dark mode chỉ cần ghi đè lớp raw:
.dark {
--gray-50: #111111; /* nền tối */
--gray-700: #a8a8a8; /* chữ phụ trên nền tối */
--gray-950: #ededed; /* chữ chính trên nền tối */
}--muted-foreground vẫn trỏ về --neutral-700, vẫn trỏ về --gray-700. Không component nào phải biết dark mode tồn tại. Cách chọn bậc cho thang kiểu này nằm ở bài thang màu Radix, còn các câu hỏi khó hơn về chế độ tối nằm ở bài câu hỏi thường gặp về dark mode.
Đừng để component gõ thẳng lớp raw (bg-gray-600). Luôn đi qua semantic (bg-muted), kể cả khi hai lớp đang trỏ tới cùng một giá trị. Ở site này, lớp raw cố ý không được nối sang Tailwind, nên bg-gray-600 không tồn tại để mà gõ nhầm.
Làm design token thế nào trong Figma (Variables) và trong code?
Trong Figma
Figma lưu token dưới dạng variable. Theo tài liệu của Figma, có sáu kiểu variable: color, number, string, boolean, và gần đây thêm timing, easing cho chuyển động. Variable được gom vào collection. Mỗi collection có thể có nhiều mode, ví dụ Light và Dark, mỗi mode giữ một giá trị cho mỗi variable. Số mode tối đa mỗi collection phụ thuộc gói Figma bạn dùng.
Cách dựng ba lớp trong Figma:
- Tạo collection
Rawchứa các thang màu thô. Ẩn collection này khỏi người dùng thư viện nếu có thể, để không ai tô màu thẳng bằng nó. - Tạo collection
Semanticvới hai mode Light và Dark. Mỗi variable ở đây trỏ tới một variable trongRawbằng aliasing. Figma chỉ cho alias tới variable cùng kiểu. - Đặt tên semantic giống hệt tên trong code:
muted-foreground,border,primary. - Trong phần Code syntax của từng variable, ghi tên dùng trong code cho Web, Android hoặc iOS. Với Web, ghi kèm
var(), ví dụvar(--muted-foreground), để Dev Mode hiện tên biến thay vì mã hex.
Bước 4 hay bị bỏ qua nhất, và nó là thứ giúp dev hoặc AI đọc file Figma ra đúng tên token. Nếu bạn dùng Claude Code, bài Figma MCP và Claude Code chỉ cách kéo variable từ Figma ra thành token CSS mà không sinh trùng.
Trong code, với Tailwind v4
Tailwind v4 cấu hình bằng CSS. Bạn khai báo theme variable trong khối @theme, và Tailwind sinh class tương ứng. Một biến trong namespace --color-* sinh ra bg-*, text-*, border-* và các class màu khác.
Site này dùng @theme inline, và chỉ nối lớp alias và semantic sang Tailwind:
@theme inline {
--color-background: var(--background);
--color-muted-foreground: var(--muted-foreground);
--color-primary: var(--primary);
--color-neutral-700: var(--neutral-700);
}Tài liệu Tailwind giải thích rằng với tuỳ chọn inline, class sẽ dùng giá trị của biến thay vì tham chiếu tới theme variable. Điều này quan trọng khi biến của bạn lại trỏ tới biến khác, như chuỗi ba lớp ở trên. Trong component, tôi chỉ viết text-muted-foreground hoặc hover:bg-muted.
Trong file JSON
Nếu cần xuất token ra iOS, Android hay một công cụ build, định dạng chuẩn là Design Tokens Format Module của W3C (bản 2025.10). Site này không dùng file JSON, nên đoạn dưới là cách token thương hiệu của tôi sẽ trông thế nào theo đặc tả:
{
"brand": {
"$type": "color",
"500": {
"$value": {
"colorSpace": "srgb",
"components": [1, 0, 0.616],
"hex": "#ff009d"
}
}
},
"primary": {
"$type": "color",
"$value": "{brand.500}",
"$description": "Nền nút chính. Không dùng cho chữ nhỏ."
}
}$value của màu là một object có không gian màu và các thành phần số, hex là trường tuỳ chọn. Tham chiếu tới token khác dùng ngoặc nhọn, ví dụ {brand.500}. Style Dictionary đọc được định dạng này từ bản 4.
Muốn AI hiểu thêm lý do đằng sau từng token, bạn cần một lớp chữ đi kèm. Bài DESIGN.md là gì giải thích cách tôi viết lớp đó.
Những sai lầm thường gặp với design token là gì?
Đặt tên theo giá trị. --pink, --gray-dark sẽ nói dối ngay khi bạn đổi màu. Tên semantic nên mô tả vai trò: --primary, --muted-foreground.
Cho component gọi lớp raw. Một #717171 gõ tay trong component là một chỗ dark mode sẽ không đổi theo.
Một token cho hai việc. Màu thương hiệu #ff009d trên nền trắng chỉ đạt tương phản 3.66:1. Đủ cho nền nút có chữ trắng, nhưng trượt chuẩn WCAG AA cho chữ nhỏ. Tôi tách thành hai token: --primary cho mảng nền, --primary-text (#be0074, 6.09:1) cho chữ magenta từ 20px trở xuống.
Thêm token cho mỗi lần thiết kế cần. Site này chỉ có ba giá trị bề mặt (#ffffff, #f8f8f8, #efefef) và bốn bậc chữ. Khi tôi thấy mình cần giá trị thứ tư, thường là bố cục đang sai.
Figma và code dùng tên khác nhau. Designer gọi Text/Secondary, code gọi muted-foreground. Mỗi lần bàn giao lại phải tra bảng. Đặt cùng tên ngay từ đầu, rồi ghi tên code vào Code syntax.
Ghi đè cả lớp semantic khi làm dark mode. Nếu thang đánh số theo khoảng cách tới nền, dark mode chỉ cần đổi lớp raw. Ghi đè từng token semantic là dấu hiệu thang chưa được thiết kế cho hai chế độ.
Bắt đầu với design token từ đâu?
Nếu bạn đang có file Figma với styles rời rạc, đừng chuyển hết một lúc. Bắt đầu với năm token semantic: nền, chữ chính, chữ phụ, viền, màu chính. Cho mỗi cái trỏ về một bậc trong thang raw. Khi cả năm chạy đúng ở chế độ sáng và tối, mở rộng dần sang trạng thái lỗi, thành công, cảnh báo. Nếu bạn mới học Figma, đọc trước bài học Figma từ số 0.
Tôi từng dựng hệ thống hơn 50 component cho Joyme, và phần khó nhất luôn là thống nhất tên token giữa Figma và code. Bạn có thể xem cách tôi làm ở case study Joyme. Nếu team bạn cần người dựng design system chạy được trên cả Figma lẫn code, xem thêm về tôi ở trang giới thiệu.
Nguồn
- Design Tokens Format Module 2025.10, W3C Design Tokens Community Group: định nghĩa token, đuôi file, cú pháp
$value,$type, tham chiếu. Bản Final Community Group Report, 28/10/2025. Truy cập 2026-10-04. - W3C Design Tokens Community Group.
- Figma: Overview of variables, collections, and modes: sáu kiểu variable, collection, mode, aliasing. Truy cập 2026-10-04.
- Figma Plugin API: setVariableCodeSyntax: ba nền tảng Web, Android, iOS cho code syntax.
- Tailwind CSS: Theme variables:
@theme, namespace--color-*, tuỳ chọninline. Truy cập 2026-10-04. - Style Dictionary: DTCG support.
app/globals.cssvàDESIGN.mdtrong repo của site này.
Câu hỏi thường gặp
- Design token có phải chỉ là màu không?
- Không chỉ màu. Đặc tả của W3C Design Tokens Community Group định nghĩa các loại như color, dimension, font family, font weight, duration, cubic Bézier, number, và các loại ghép như border, shadow, typography. Màu thường là nơi người ta bắt đầu vì nó dễ thấy nhất.
- Design token và Figma Variables có giống nhau không?
- Figma Variables là cách Figma lưu token trong file thiết kế: có collection, mode sáng/tối, và cho một variable trỏ tới variable khác (aliasing). Token là khái niệm rộng hơn. Cùng một token có thể sống trong Figma, trong CSS và trong file JSON.
- Có định dạng file chuẩn cho design token không?
- Có. Design Tokens Community Group của W3C công bố bản Design Tokens Format Module 2025.10 vào ngày 28/10/2025. File dùng đuôi .tokens hoặc .tokens.json, mỗi token có $value và $type, tham chiếu tới token khác bằng cú pháp ngoặc nhọn.
- Dự án nhỏ có cần ba lớp token không?
- Nên có ngay từ đầu, vì chi phí thấp: lớp alias chỉ là vài chục dòng trỏ tới lớp raw. Thứ có thể để sau là công cụ chuyển đổi như Style Dictionary, chỉ cần khi token phải xuất ra nhiều nền tảng.
Có thể bạn quan tâm
Claude Code là gì? Cài đặt và chạy lệnh đầu tiên khi chưa biết code
Hướng dẫn cho người chưa từng mở terminal: Claude Code là gì, cần chuẩn bị gì, cài trên macOS và Windows, chạy phiên đầu tiên và sửa các lỗi hay gặp. Mọi lệnh lấy từ tài liệu chính thức của Anthropic.
Working· 2026-10-04
Claude Code cho designer: biến thiết kế Figma thành trang chạy được
Cách một designer dùng Claude Code để đưa thiết kế từ Figma thành trang web thật: chuẩn bị gì, viết quy tắc cho AI ra sao, quy trình sáu bước và những lỗi tôi đã gặp khi dựng chính site này.
Working· 2026-10-04
Claude là gì? Hướng dẫn cho người chưa dùng AI bao giờ
Claude là trợ lý AI của Anthropic. Bài này giải thích Claude làm được gì, gói miễn phí và trả phí khác nhau ra sao, cách mở cuộc trò chuyện đầu tiên, và những chỗ Claude hay sai mà người mới nên biết. Mọi tính năng và giá đều kiểm ở trang chính thức.
Working· 2026-10-04