Handoff Figma → CSS: chuyển HEX / RGB / HSL không lệch brand【2026】

(Cập nhật: 19 tháng 7, 2026 ) HEX RGB HSL Figma CSS design token color converter
Kết luận

Lệch brand khi handoff Figma → CSS gần như luôn đến từ quy trình, không phải từ ‘công thức sai’. Khóa một nguồn sự thật (thường #RRGGBB), sinh RGB/HSL từ đó, và đừng nhân opacity hai lần. Color converter giúp đối chiếu HEX ↔ RGB (và Unity Color 0–1) ngay trên trình duyệt — không cần đăng ký, phù hợp freelance và team outsourcing Việt Nam.

Designer gửi chip #6366F1. Dev dán vào Tailwind. QA mở staging: nút “tím hơn một chút”, hoặc nhạt hơn vì layer Figma đang 80% opacity trong khi CSS lại opacity: 0.8 lần nữa. Ticket “fix màu brand” — quen thuộc với team product và studio outsource.

Bài này tập trung handoff Figma → CSS: khi nào dùng HEX / RGB / HSL, cách chuyển không lệch, lỗi hay gặp, và checklist token. Không phải bài định nghĩa màu học thuật.

Bài viết này giúp bạn

  • Hiểu vì sao cùng HEX vẫn lệch giữa mock và production
  • Chọn HEX / RGB / HSL đúng ngữ cảnh (token, CSS, chỉnh theme)
  • ví dụ số và bảng so sánh — không chỉ lý thuyết
  • checklist trước khi merge PR màu
  • Biết dùng color converter để đối chiếu nhanh, local

Vì sao handoff Figma → CSS dễ lệch brand?

Ba nguồn lệch phổ biến nhất trong team Việt (freelance, agency, product):

  1. Nhiều nguồn sự thật — Figma Styles ghi HEX, ticket Slack gửi rgb(), PR dùng hsl() làm tròn khác nhau.
  2. Opacity kép — fill 100% + layer 70% trên Figma; CSS ghi cả alpha trong màu opacity trên wrapper.
  3. Làm tròn chuỗi — HEX → HSL (tool A) → RGB (tool B) → HEX lại: lệch 1–2 đơn vị kênh, mắt vẫn thấy trên nền tương phản cao.

Màu là số. Bug là đơn vị và quy ước team, không phải “CSS không hiểu Figma”.


HEX, RGB, HSL — cùng màu, ba việc khác nhau

Khi nào dùng từng dạng
Dạng Ví dụ Phù hợp handoff
HEX #6366F1 Token brand, Tailwind, chia sẻ Slack/Notion. Nguồn sự thật mặc định.
RGB / RGBA rgb(99 102 241) Inspector, Canvas, blend; alpha rõ ràng bằng số 0–1 hoặc %.
HSL / HSLA hsl(239 84% 67%) Chỉnh sáng/tối theme, hover/pressed từ cùng hue — không thay brand gốc bằng mắt.

HEX — nguồn sự thật cho brand

#RRGGBB: mỗi cặp hex = một kênh 0–255.

Ví dụ indigo Tailwind-ish:

KênhHEXThập phân
R6399
G66102
BF1241

→ CSS: #6366F1 hoặc rgb(99, 102, 241).

Quy ước team: luôn uppercase hoặc luôn lowercase trong repo — đừng mix #6366f1#6366F1 trong diff nếu linter chưa normalize (review ồn, git blame rối).

RGB — khi cần alpha hoặc debug kênh

/* Cùng màu fill */
--brand-primary: #6366f1;
--brand-primary-rgb: 99 102 241; /* tiện cho rgb(var(--brand-primary-rgb) / 0.4) */

Pattern R G B space-separated giúp đổi alpha mà không copy lại ba số:

.btn-ghost {
  background: rgb(var(--brand-primary-rgb) / 40%);
}

HSL — chỉnh biến thể, không thay thế token gốc

HSL tách hue / saturation / lightness. Tiện khi:

  • Dark mode: giữ hue, hạ lightness có kiểm soát
  • Hover: tăng lightness 4–8% thay vì chọn màu mới bằng mắt trên Figma

Cảnh báo: HSL từ tool khác nhau làm tròn khác nhau (67% vs 66.9%). Nếu commit cả HEX lẫn HSL “tương đương”, sau vài vòng chuyển đổi sẽ lệch. Cách an toàn:

  1. Token gốc = HEX
  2. HSL chỉ sinh khi cần biến thể, ghi rõ công thức trong comment hoặc design token JSON
  3. Không round-trip HSL → HEX trong CI trừ khi có test snapshot

Quy trình handoff 4 bước (Figma → CSS)

1. Lấy fill thuần, rồi mới tính opacity

Trên Figma: chọn layer → copy HEX của fill. Nếu layer opacity ≠ 100%, ghi riêng:

  • Fill: #6366F1
  • Layer opacity: 70%

CSS chỉ được áp một trong hai:

/* Cách A: alpha trong màu */
.chip { background: #6366f1b3; } /* ~70% nếu AA = B3 */

/* Cách B: opacity phần tử — đừng kết hợp với A */
.chip { background: #6366f1; opacity: 0.7; } /* ảnh hưởng cả chữ bên trong */

opacity trên phần tử làm mờ cả children — thường sai cho nút có chữ. Ưu tiên alpha trên nền.

2. Đối chiếu HEX ↔ RGB một lần

Mở chuyển đổi màu (color converter), dán #6366F1 (hoặc chọn bằng color picker):

  • RGB hiển thị: 99, 102, 241
  • Nếu team Unity/C#: thêm new Color(0.388f, 0.400f, 0.945f) (chia 255) — tránh dán nhầm new Color(99, 102, 241) (sai đơn vị 0–1)

Công cụ chạy local trên trình duyệt, không cần tài khoản — phù hợp khi palette brand chưa public.

3. Sinh HSL có chủ đích (nếu cần)

Ví dụ gần đúng cho #6366F1:

/* Nguồn: HEX */
--color-primary: #6366f1;

/* Biến thể — HSL chỉnh L, không đổi H/S lung tung */
--color-primary-hover: hsl(239 84% 72%);
--color-primary-pressed: hsl(239 84% 58%);

Ghi trong PR: “hover = +5% L từ primary”. Reviewer kiểm được; mắt không phải nguồn sự thật.

4. Kiểm tra trên nền product + contrast

Mock Figma thường nền sáng. Product có sidebar tối / card xám. Cùng #6366F1 trên nền #0F172A nhìn “cháy” hơn trên #FFFFFF. Sau khi gắn token, chạy kiểm tra contrast cho chữ trên nền brand (AA tối thiểu cho text thường).


Ví dụ số: một màu — ba dạng — một token

Giả sử brand primary = indigo #6366F1.

Cùng màu primary — các dạng hợp lệ
Ngữ cảnh Giá trị Ghi chú
Token CSS --color-primary: #6366f1 Nguồn sự thật
RGB kênh 99, 102, 241 Đối chiếu converter / Canvas
CSS modern rgb(99 102 241 / 1) Alpha tách
HSL (gần) hsl(239 84% 67%) Chỉ để biến thể; đừng round-trip
Unity Color new Color(0.388f, 0.400f, 0.945f) 0–1 float, không phải 0–255
Unity Color32 new Color32(99, 102, 241, 255) Giữ byte 0–255

Sai điển hình trong sprint game + web (outsourcing phổ biến ở VN):

// SAI — Unity Color kỳ vọng 0–1
var c = new Color(99f, 102f, 241f);

// ĐÚNG
var c = new Color(99f / 255f, 102f / 255f, 241f / 255f);
// hoặc copy từ color converter

Web team và Unity team phải dùng cùng HEX gốc; mỗi bên convert một lần theo đơn vị của platform.


Checklist trước khi merge PR màu

Checklist handoff màu
Mục Hỏi nhanh
Một nguồn Token primary chỉ xuất hiện một lần (theme file)? Không hard-code lại trong 4 component?
Opacity Alpha chỉ ở một chỗ (màu hoặc CanvasGroup / opacity wrapper)?
Đối chiếu HEX trong Figma Styles = HEX trong CSS (diff exact)?
HSL Nếu có HSL: có comment công thức? Có test visual/regression không?
Nền thật Đã xem trên light + dark (hoặc nền product) chứ không chỉ artboard trắng?
Contrast Chữ trên nền brand đạt AA? Primary nhạt trên nền sáng thường fail.
Tên primary / brand / accent thống nhất với design system — không purple2 vs indigo.

Case study ngắn

Case 1: Freelance — client Figma, bạn Next.js + Tailwind

Tình huống: Client gửi file Figma, Styles tên Brand/Primary. Bạn map vào tailwind.config / @theme.

Làm: Copy HEX từ Styles (không eyedrop artboard đã overlay). Đặt --color-primary. Biến thể hover bằng HSL +ΔL hoặc shade cố định trong palette. Đối chiếu RGB bằng color converter trước khi gửi preview.

Tránh: Eyedrop screenshot Slack (JPEG lệch); copy màu từ layer đang 50% opacity rồi trách CSS “sai”.

Case 2: Team outsourcing — web UI + Unity client cùng brand

Tình huống: App web marketing và game client phải cùng indigo.

Làm: File brand-colors.json chỉ chứa HEX. Web import CSS variable; Unity sinh Color/Color32 từ cùng HEX (tool hoặc helper một chỗ). Không chat “khoảng 99,100,240”.

Tránh: Designer gửi HSL từ plugin A; Unity artist nhập RGB từ plugin B — hai bên “gần đúng”, build store lệch.

Case 3: Dark mode làm lệch primary

Tình huống: Light dùng #6366F1; dark tự giảm opacity toàn cục → nút trông bẩn.

Làm: Token riêng --color-primary-dark (HEX chọn có chủ đích) hoặc HSL hạ L có kiểm soát; không opacity: 0.85 lên cả button.


Lỗi thường gặp

  1. Round-trip HSL — HEX → HSL → HEX khác 1 digit → “brand drift” sau 3 PR.
  2. Opacity kép — Figma layer × CSS alpha.
  3. Unity 0–255 vào Color — glow / clip. Dùng converter hoặc Color32.
  4. Eyedrop ảnh nén — luôn lấy từ Styles / Inspect.
  5. Hard-code rải rác#6366f1 trong 12 file; đổi brand = 12 diff sót. Gom token.

Cách dùng color converter (Kawa)

  1. Mở Color converter — HEX / RGB / Unity
  2. Dán #6366F1 hoặc chọn color picker
  3. Đọc RGB 99, 102, 241; copy Unity new Color(...) nếu cần
  4. Lịch sử ~5 màu gần nhất — tiện khi map cả palette primary/success/danger

Giới hạn trung thực: tool tập trung HEX ↔ RGB ↔ Unity Color, xem trước và lịch sử local. Phần HSL trong bài là quy ước CSS/handoff — hãy sinh HSL từ token HEX bằng một pipeline cố định (PostCSS, Style Dictionary, hoặc công thức team), đừng tin vào ba tool online khác nhau trong cùng một PR.

Liên quan: rgba ↔ hex, color contrast WCAG, Tailwind color.


Tóm tắt

  • Khóa HEX làm nguồn brand; RGB/HSL là dạng xuất.
  • Một lần opacity — không nhân Figma × CSS.
  • Đối chiếu số, không đối chiếu mắt trên artboard trắng.
  • Web + Unity: cùng HEX, convert theo đơn vị platform.
  • Dùng color converter để xác nhận HEX/RGB (và Unity) không cần đăng ký, chạy trên trình duyệt.

Handoff sạch = ít ticket “màu hơi lệch” — và brand nhìn thống nhất từ Figma tới production.