Thêm màu brand vào Tailwind CSS | Custom color palette từ HEX (v3/v4)

(Cập nhật: 19 tháng 7, 2026 ) Tailwind CSS custom color brand HEX design token theme.extend v3 v4
Kết luận

Thêm màu brand bằng theme.extend (v3) hoặc @theme (v4) — không ghi đè toàn bộ theme.colors. Đưa HEX thành scale có tên (brand-500), giữ class chuỗi đầy đủ trong source, và chỉ tạo custom khi HEX lệch rõ khỏi palette mặc định. Công cụ màu Tailwind giúp map HEX → class gần nhất trước khi sửa config.

Designer gửi #0F766E#CCFBF1. Bạn thêm bg-brand — local ổn. Deploy lên Vercel/Netlify: class biến mất, hoặc tệ hơn là cả text-gray-500 trong app cũng biến mất vì bạn đã thay palette mặc định. Custom color trong Tailwind không khó — khó ở chỗ hình dạng config, content scan, và cách viết class không khớp nhau.

Bài này dành cho frontend Việt Nam (freelance, team outsourcing Next/React/Astro, sinh viên làm đồ án) khi nhận brief từ client Nhật/Mỹ hoặc agency nội địa: đưa HEX brand vào Tailwind đúng cách, v3 và v4.

Ai cần đọc bài này

  • Dev nhận file Figma chỉ có swatch HEX, không có token Tailwind
  • Team monorepo (apps/web + packages/ui) từng mất utility trên CI
  • Ai đang migrate Tailwind v3 → v4 và bối rối chỗ @theme
  • Designer/dev cần thống nhất tên brand-500 thay vì brandPrimaryDarkest

Custom color trong Tailwind là gì?

Custom color là màu bạn thêm vào theme để dùng như utility: bg-brand-500, text-primary, border-accent/40. Không phải hard-code style={{ color: '#0F766E' }} rải khắp component.

Hai hướng phổ biến:

  1. Map HEX → màu mặc định gần nhất (teal-700, sky-500) — ít config, đồng bộ với docs Tailwind
  2. Extend namespace riêng (brand, primary) — đúng khi brand lệch palette hoặc cần semantic rename sau này
Map mặc định vs extend brand
Cách Ưu Khi nào chọn
Dùng blue-500 / zinc-700 sẵn Không đụng config; docs và plugin quen thuộc HEX gần scale mặc định; UI nội bộ, MVP
extend colors.brand Đổi HEX một chỗ; class semantic ổn định Brand riêng; design system; bàn giao client dài hạn
CSS variable + theme Dark mode / white-label đổi runtime SaaS đa tenant, theme switcher

Muốn biết HEX có “gần” teal-700 không: dán vào công cụ tìm màu Tailwind (chạy trên trình duyệt, không cần đăng ký). Nếu Delta E nhỏ — cân nhắc dùng utility mặc định thay vì nhân đôi palette.


v3: extend — đừng clobber

Cấu hình đúng

// tailwind.config.ts (Tailwind v3)
import type { Config } from "tailwindcss";

export default {
  content: ["./src/**/*.{html,js,ts,jsx,tsx,astro}"],
  theme: {
    extend: {
      colors: {
        brand: {
          50: "#f0fdfa",
          100: "#ccfbf1",
          500: "#0f766e",
          700: "#115e59",
          DEFAULT: "#0f766e",
        },
      },
    },
  },
} satisfies Config;

Sau đó dùng: bg-brand, bg-brand-500, text-brand-700, ring-brand/30.

Sai lầm hay gặp

// ❌ Thay toàn bộ palette mặc định
theme: {
  colors: {
    brand: { 500: "#0f766e" },
  },
}

Mọi bg-gray-100, text-red-600 biến mất khỏi CSS build. Local có thể “vẫn xanh” vì bạn chỉ nhìn vài màn brand — production mới lộ khi trang auth/error dùng gray/red mặc định.

Quy tắc: merge bằng extend trừ khi redesign cố ý bỏ default scale.


v4: thêm token bằng @theme

Tailwind v4 đẩy nhiều token sang CSS. Cùng tư duy “thêm, không xóa”:

/* app.css — Tailwind v4 */
@import "tailwindcss";

@theme {
  --color-brand-50: #f0fdfa;
  --color-brand-100: #ccfbf1;
  --color-brand-500: #0f766e;
  --color-brand-700: #115e59;
  --color-brand: #0f766e;
}

Utility sinh ra tương tự: bg-brand-500, text-brand. Nếu project còn tailwind.config legacy, kiểm tra docs phiên bản bạn đang dùng — đừng copy lẫn khối v3 vào dự án v4 thuần CSS.

v3 vs v4 — nơi khai báo màu
Phiên bản Nơi chính Lưu ý
Tailwind v3 tailwind.config → theme.extend.colors content globs quyết định class nào vào CSS
Tailwind v4 @theme trong CSS (+ config tùy dự án) Tên --color-* map sang utility; tránh trùng token mặc định nếu không cố ý

Từ dump HEX Figma → scale dùng được

Designer outsourcing thường gửi 3–5 HEX, không phải thang 50–950. Bạn vẫn cần tên khớp cách viết utility.

Nhu cầuCách làm
Một accentbrand / brand-DEFAULT + brand-soft / brand-dark
UI đầy đủMap hoặc generate 50–900; 500 = màu chính
Giữ gray TailwindGiữ zinc/slate mặc định; chỉ thêm brand

Quy ước đặt tên (handoff designer ↔ dev)

  • Gọi bậc chính brand-500 (hoặc DEFAULT) — cùng ngôn ngữ với Figma styles
  • Tránh one-off: brandPrimaryDarkestHover không map được sang scale
  • Semantic (primary, danger, success) khi màu có thể đổi theo brand mà class JSX giữ nguyên

Checklist 10 phút trước khi sửa config:

  1. HEX chính → 500 / DEFAULT
  2. Soft background → 50100
  3. Text trên nền sáng → 700900 (đo contrast)
  4. So HEX với palette Tailwind — tránh trùng gần teal-700 rồi tạo brand song song không cần thiết

Opacity /50 và CSS variable

bg-brand/50 cần channel alpha. HEX trực tiếp trong config thường vẫn hoạt động trên Tailwind v3 gần đây, nhưng pattern bền hơn cho dark mode:

:root {
  --color-brand-500: 15 118 110; /* R G B, không # */
}
.dark {
  --color-brand-500: 45 212 191;
}
// v3 theme.extend.colors
brand: {
  500: "rgb(var(--color-brand-500) / <alpha-value>)",
}

Đổi theme = đổi biến, không regenerate tên utility. Phù hợp SaaS white-label hoặc landing campaign Tết đổi palette tạm.


Bẫy class động — lý do “mất màu” trên production

// Nguy hiểm — scanner có thể không thấy bg-brand-500
const shade = "500";
return <div className={`bg-brand-${shade}`} />;

JIT/content scan tìm chuỗi class đầy đủ trong source. Nối chuỗi ẩn mất chúng.

Cách xử lý:

const shadeClass = {
  500: "bg-brand-500",
  700: "bg-brand-700",
} as const;

return <div className={shadeClass[500]} />;

Hoặc dùng CSS variable + style / utility cố định tham chiếu biến. Safelist chỉ khi thực sự dynamic và có kiểm soát — đừng safelist cả thang màu “cho chắc”.

Monorepo quên glob

apps/web/src/**           ✓
packages/ui/src/**        ← quên; Button bg-brand không được scan

Sau khi thêm màu: search repo chuỗi bg-brand-500, rồi mở CSS build xác nhận selector tồn tại.


Case study ngắn

1) Agency VN — landing SME từ Figma JP

Brief: logo #E11D48, nền #FFF1F2. Dev map rose-600 / rose-50 qua công cụ màu Tailwind — đủ gần, không cần extend. PR gọn, designer chấp nhận “gần brand trong ngưỡng”.

2) Product outsourcing — brand lệch scale

Fintech dùng teal #0F766E làm CTA, cần brand riêng vì marketing đổi HEX theo quý. Team dùng extend + CSS variable, checklist PR: không clobber colors, không template string class, contrast AA trên nút. Deploy ổn định qua 3 tenant.


Checklist trước khi merge PR palette

  1. Màu nằm trong extend hoặc @theme bổ sung — không wipe default
  2. Mọi utility trong JSX tồn tại dạng literal đầy đủ (hoặc map object)
  3. content / source globs cover mọi package dùng class đó
  4. Dark mode: biến CSS hoặc class cặp — không “nhớ chỉnh HEX sau”
  5. Document 500/DEFAULT cho designer; đo contrast text/CTA trên nền thật
  6. (Tuỳ chọn) So HEX với default Tailwind trước — tránh duplicate gần giống

Cách dùng công cụ trên Kawa

  1. Mở Màu Tailwind
  2. Dán HEX từ Figma hoặc brand guideline
  3. Xem class gần nhất (ví dụ teal-700) và khoảng cách màu
  4. Quyết định: dùng default hay extend namespace brand
  5. Copy tên/scale vào config hoặc @theme

Công cụ chạy trong trình duyệt — phù hợp khi HEX nằm trong brief nội bộ, không muốn upload lên service lạ.


Liên kết liên quan