Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là designer tại một startup fintech ở TP.HCM. Sản phẩm của bạn — một app quản lý chi tiêu — vừa được sếp yêu cầu bổ sung Dark Mode trong vòng hai tuần. Bạn mở file Figma và giật mình: toàn bộ màu sắc trong 120 màn hình đang được gán bằng Color Styles cố định. Nền trắng, chữ đen, thẻ màu xám nhạt. Để làm Dark Mode theo cách cũ, bạn phải duplicate toàn bộ file, đổi tay từng màu, và rồi mỗi lần thiết kế thay đổi, bạn phải sửa ở… hai nơi. Đây chính xác là "cơn ác mộng" mà rất nhiều team gặp phải trước năm 2023.
Figma Variables ra đời để giải quyết đúng bài toán này. Nếu ở Bài 14 bạn đã hiểu Design Tokens là "lớp nền" (foundation layer) chứa các quyết định thiết kế, thì Bài 15 là nơi bạn học cách hiện thực hóa tokens đó ngay bên trong Figma bằng công cụ Variables — đặc biệt là hai siêu năng lực của nó: Modes (chế độ) và aliasing (tham chiếu). Đây là kỹ năng phân biệt một UI designer "biết dùng Figma" với một người "làm được design system thực thụ". Khi nắm vững Variables, việc retheme cả sản phẩm — từ Light sang Dark, từ brand A sang brand B, từ ngôn ngữ này sang ngôn ngữ khác — có thể chỉ mất vài cú click thay vì vài ngày lao động thủ công.
Khái niệm cốt lõi
Styles (legacy) — cách làm cũ và giới hạn của nó
Trước Variables, Figma chỉ có Styles: Color Styles, Text Styles, Effect Styles. Về bản chất, một Style là một "gói thuộc tính" được đặt tên. Ví dụ bạn tạo Color/Primary = #2563EB. Mỗi lần cần màu chủ đạo, bạn gán style đó.
Vấn đề nằm ở hai điểm:
- Style mang tính "string-based" và tĩnh. Một Color Style chỉ chứa đúng một giá trị. Nó không biết "màu này khi ở Dark Mode thì đổi thành gì". Muốn có phiên bản Dark, bạn phải tạo một bộ styles riêng (ví dụ
Color/Primary-Dark) và gán lại thủ công cho từng layer — hoặc tệ hơn, duplicate cả file. - Không có khả năng tham chiếu (alias). Style không thể "trỏ" tới một style khác. Nếu 40 style của bạn cùng dùng chung một sắc xanh, và sắc xanh đó cần đổi, bạn phải sửa 40 lần.
Variables — giá trị nguyên thủy có thể tham chiếu và đổi theo mode
Variable (biến) là một giá trị được đặt tên mà bạn có thể tái sử dụng khắp file. Figma hỗ trợ 4 loại:
- Color — màu sắc (fill, stroke).
- Number — số (spacing, radius, kích thước, thậm chí opacity).
- String — chuỗi văn bản (nội dung, tên ngôn ngữ, giá trị theme).
- Boolean — đúng/sai (dùng để bật/tắt hiển thị layer qua conditional).
Modes — trái tim của theming
Mode là khả năng cho một variable mang nhiều giá trị khác nhau tùy ngữ cảnh. Một variable bg/surface có thể có giá trị #FFFFFF ở mode "Light" và #0F172A ở mode "Dark". Cùng một biến, hai giá trị.
Modes được tổ chức bên trong Variable Collection (bộ sưu tập biến). Một collection có thể chứa nhiều modes. Khi bạn gán biến bg/surface cho một frame và đặt frame đó ở mode "Dark", Figma tự động hiển thị giá trị Dark. Đổi mode ở cấp frame → toàn bộ giao diện bên trong đổi theo. Đây chính là cơ chế biến "làm Dark Mode 2 tuần" thành "làm Dark Mode 2 giờ".
Lưu ý gói tài khoản: số lượng modes mỗi collection bị giới hạn theo plan. Free chỉ 1 mode/collection, Professional cho phép tới 4 modes, Organization/Enterprise cho nhiều hơn (thường 40). Đây là yếu tố bạn cần cân nhắc khi thiết kế cấu trúc theming.
Aliasing — kiến trúc hai lớp Primitive → Semantic
Đây là khái niệm nâng nhất và cũng quan trọng nhất. Bạn nên tổ chức variables thành hai lớp:
- Lớp Primitive (raw) — bảng màu thô, không mang ý nghĩa ngữ cảnh:
blue/500 = #2563EB,slate/900 = #0F172A,white = #FFFFFF. Lớp này thường chỉ có 1 mode. - Lớp Semantic (alias) — biến mang ý nghĩa và trỏ tới primitive:
bg/surface,text/primary,border/default. Lớp này chứa nhiều modes (Light/Dark).
bg/surface alias tới white; ở mode Dark, bg/surface alias tới slate/900. Layer trong thiết kế chỉ được gán biến semantic, không bao giờ gán trực tiếp primitive. Nhờ đó, khi cần đổi toàn bộ tông xanh của brand, bạn chỉ sửa blue/500 một lần — mọi thứ trỏ tới nó tự cập nhật.Tình huống thực tế
Tình huống 1 — MoMo và bài toán Dark Mode "một đêm"
Giả định một team design system tại một ví điện tử lớn như MoMo cần triển khai Dark Mode cho app có hơn 200 màn hình. Ban đầu họ ước tính 3 tuần vì đang dùng Color Styles cố định. Sau khi migrate sang Variables với kiến trúc hai lớp, câu chuyện đổi hẳn.
Họ tạo collection Primitives chứa ~60 màu thô (các sắc hồng thương hiệu, xám, trắng, đen). Rồi collection Theme với hai modes Light/Dark, gồm khoảng 25 biến semantic như bg/base, bg/elevated, text/primary, text/muted, brand/accent. Mỗi biến semantic được alias vào primitive tương ứng cho từng mode.
Vì mọi component trong library đều đã gán biến semantic, việc "bật Dark Mode" chỉ còn là đổi mode ở frame gốc. Toàn bộ 200 màn hình đổi màu theo. Phần thời gian thực sự tốn không phải là "đổi màu" mà là tinh chỉnh — ví dụ shadow trong Dark cần nhẹ hơn, một vài màu accent cần bão hòa lại cho dễ đọc.
Bài học: giá trị lớn nhất của Variables không phải tiết kiệm click, mà là biến việc retheme từ thủ công thành hệ thống. Đầu tư vào lớp semantic trả lãi kép mỗi lần thêm theme mới.
Tình huống 2 — Agency Sài Gòn phục vụ nhiều brand bằng "brand modes"
Một agency thiết kế ở Sài Gòn nhận làm sản phẩm SaaS white-label: cùng một app, bán cho 3 ngân hàng khác nhau, mỗi ngân hàng có bộ nhận diện riêng (một bên xanh dương, một bên đỏ, một bên xanh lá). Trước đây họ phải maintain 3 file Figma song song — một cơn ác mộng khi client yêu cầu sửa layout chung.
Với Variables, họ dùng modes theo một chiều khác: thay vì Light/Dark, collection Brand có 3 modes là Bank-A, Bank-B, Bank-C. Biến brand/primary, brand/secondary, brand/logo-tint mang giá trị khác nhau ở mỗi mode. Chỉ cần đổi mode ở artboard demo, họ pitch được cả 3 phiên bản brand cho client ngay trong một buổi họp, từ đúng một file thiết kế.
Điểm tinh tế: họ tách hai collection riêng — một Brand (3 modes) và một Appearance (Light/Dark). Nhờ tách collection, hai trục theming độc lập nhau: Bank-A + Dark, Bank-C + Light… kết hợp tự do mà không nổ tổ hợp trong một collection duy nhất.
Bài học: Modes không chỉ dành cho Dark Mode. Bất kỳ trục biến đổi nào — brand, density (compact/comfortable), platform — đều có thể là một mode. Và tách các trục thành nhiều collection để tránh phải liệt kê mọi tổ hợp.
Tình huống 3 — Sự cố "màu cứng" của bạn junior
Một designer junior tại một team product ở Hà Nội được giao vẽ màn hình Settings. Bạn ấy dùng đúng biến semantic cho nền và chữ, nhưng ở phần icon lại "tiện tay" gõ thẳng #FFFFFF vì thấy nó trắng giống nền card. Mọi thứ trông ổn ở Light Mode.
Đến sprint sau, team bật Dark Mode. Toàn bộ màn hình đổi màu mượt mà — trừ mấy cái icon đó, vẫn trắng lóa trên nền tối, gần như tàng hình. Vì #FFFFFF là giá trị cứng, nó không biết mode là gì. Team mất thời gian đi soi từng layer để tìm ra chỗ "màu cứng" lọt lưới.
Bài học: kỷ luật quan trọng hơn công cụ. Một Variable system chỉ mạnh khi 100% các layer đều gán biến semantic, không có ngoại lệ "tiện tay". Nhiều team giải quyết bằng cách chạy plugin kiểm tra để phát hiện màu hardcode trước khi ship.
Hướng dẫn từng bước
Ta sẽ dựng một hệ theming Light/Dark tối giản nhưng đúng chuẩn.
Bước 1 — Mở panel Variables. Ở file Figma, bỏ chọn mọi layer, mở panel Design bên phải, tìm mục Variables (biểu tượng ở phần Local variables), bấm để mở cửa sổ quản lý biến.
Bước 2 — Tạo collection Primitives. Bấm "Create collection", đặt tên 1. Primitives. Thêm các Color variable thô: white = #FFFFFF, slate/50 = #F8FAFC, slate/900 = #0F172A, blue/500 = #2563EB, blue/400 = #60A5FA. Đặt tên theo cấu trúc nhóm/tên bằng dấu / để Figma tự gom nhóm gọn gàng. Collection này chỉ cần 1 mode.
Bước 3 — Tạo collection Theme với 2 modes. Tạo collection thứ hai tên 2. Theme. Trong đó, đổi tên mode mặc định thành Light, rồi bấm dấu + bên cạnh header mode để thêm mode Dark.
Bước 4 — Tạo biến semantic và alias chúng. Thêm các biến: bg/base, bg/card, text/primary, brand/accent. Với mỗi ô giá trị (từng mode), thay vì gõ mã màu, hãy bấm vào ô và chọn biểu tượng alias (mắt xích/hình thoi) để trỏ tới primitive:
bg/base: Light →white, Dark →slate/900.text/primary: Light →slate/900, Dark →white.brand/accent: Light →blue/500, Dark →blue/400.
bg/base. Chọn text chọn text/primary, nút CTA chọn brand/accent. Tuyệt đối không gõ mã hex trực tiếp.Bước 6 — Đổi mode để kiểm tra. Chọn frame ngoài cùng, trong panel Design tìm mục hiển thị mode của collection Theme, gạt từ Light sang Dark. Toàn bộ giao diện bên trong đổi màu. Nếu có layer nào không đổi, đó là "màu cứng" cần sửa.
Bước 7 — Publish (nếu dùng library). Nếu file là design system dùng chung, publish collection lên team library để các file khác kế thừa biến.
Lỗi thường gặp & mẹo
- Gán primitive trực tiếp vào layer. Đây là lỗi phổ biến nhất. Layer phải gán biến semantic; primitive chỉ để semantic tham chiếu. Nếu gán primitive thẳng, bạn mất khả năng đổi mode.
- Nhồi mọi thứ vào một collection nhiều modes. Khi bạn có cả Light/Dark lẫn nhiều brand trong một collection, số mode nổ theo cấp số nhân (3 brand × 2 appearance = 6 mode). Hãy tách thành các collection độc lập theo từng trục.
- Quên giới hạn mode theo plan. Bạn thiết kế 4 modes rồi đưa cho đồng nghiệp dùng bản Free — họ chỉ thấy 1 mode. Kiểm tra plan của cả team trước khi cam kết kiến trúc.
- Đặt tên lộn xộn.
color1,myBlue,NewColorkhiến hệ thống mau rối. Dùng cấu trúcnhóm/vai-trò/biến-thểnhất quán nhưbg/card,text/muted,border/focus. (Quy ước đặt tên sẽ được đào sâu ở Bài 34.) - Mẹo — dùng Number variable cho spacing và radius. Variables không chỉ cho màu. Tạo biến
radius/md = 8,space/4 = 16và gán vào corner radius, padding auto layout. Sau này đổi hệ số bo góc toàn app chỉ bằng một biến. - Mẹo — kiểm tra bằng cách "flip mode sớm". Ngay khi vẽ xong một component, gạt thử Dark Mode. Bắt lỗi màu cứng lúc còn nhỏ dễ hơn nhiều so với khi đã lan ra trăm màn hình.
Bài tập thực hành
- Dựng bộ theming tối giản. Tạo hai collection
Primitives(ít nhất 6 màu thô) vàTheme(2 modes Light/Dark, ít nhất 5 biến semantic được alias đầy đủ). - Thiết kế một Card component gồm nền, tiêu đề, mô tả phụ, một nút CTA — gán 100% bằng biến semantic, không có mã hex nào gõ tay.
- Flip mode và chụp lại. Đổi mode sang Dark, chụp cả hai phiên bản đặt cạnh nhau. Tự kiểm: có layer nào không đổi màu không? Nếu có, đó là màu cứng — sửa lại.
- Thử nghiệm trục thứ hai. Tạo thêm collection
Densityvới hai modesComfortable/Compact, dùng Number variable cho padding, và quan sát cách một Card thay đổi khoảng cách khi đổi mode — mà màu sắc vẫn độc lập. - Viết một đoạn ngắn (5–7 dòng) giải thích cho một đồng nghiệp junior: vì sao không nên gán primitive trực tiếp vào layer.
Tóm tắt
Variables là bước tiến lớn nhất của Figma trong việc biến Design Tokens từ ý tưởng thành công cụ vận hành được. Khác với Styles cũ — tĩnh, không tham chiếu, phải duplicate cả file để retheme — Variables cho bạn giá trị nguyên thủy, khả năng alias, và trên hết là Modes để một biến mang nhiều giá trị theo ngữ cảnh. Kiến trúc chuẩn là hai lớp: Primitive (bảng màu thô, 1 mode) và Semantic (biến mang ý nghĩa, nhiều modes, alias vào primitive) — và layer trong thiết kế chỉ được gán biến semantic. Nắm vững nguyên tắc này, bạn không chỉ làm được Dark Mode trong vài giờ thay vì vài tuần, mà còn mở khóa mọi trục theming khác: brand, density, platform. Kỷ luật "không màu cứng" và thói quen "flip mode sớm" là hai thứ giữ cho hệ thống của bạn sạch và bền. Ở các bài tiếp theo, bạn sẽ dùng chính nền tảng Variables này để dựng một Color System và Typography System hoàn chỉnh trong Figma.