Bỏ qua, sang nội dung chính
← Về danh sách

· Working

Tailwind cho designer: đọc code AI viết ra mà không sợ

Cách đọc một chuỗi class Tailwind theo nhóm, bảng class thường gặp và CSS tương ứng, ý nghĩa của hover:, md:, dark:, token nằm ở đâu trong theme, và cách bắt AI dùng token thay vì giá trị gõ cứng. Ví dụ lấy từ code thật của site này.

Một class Tailwind gần như là một dòng CSS viết tắt: p-4 là padding 16px, flex là display: flex, hover:bg-muted là đổi nền khi rê chuột. Đọc code Tailwind do AI viết ra, bạn chỉ cần chia chuỗi class thành nhóm (bố cục, khoảng cách, chữ, màu, trạng thái) và kiểm từng nhóm có dùng token của hệ thống không.

Tôi là Hai Le, UI/UX designer hơn 5 năm, viết được React và Tailwind. Site này dùng Tailwind CSS 4.3, mọi ví dụ dưới đây là code thật trong repo. Chưa chắc về flexbox, hãy đọc designer cần biết HTML/CSS đến mức nào trước.

Đọc một chuỗi class Tailwind như thế nào?

Đây là một tab lọc ở trang Blog của site này, gộp phần class chung với phần class của tab chưa được chọn:

className="type-body-sm flex h-9 items-center rounded-md px-3 whitespace-nowrap
  text-muted-foreground hover:bg-muted hover:text-foreground
  transition-colors duration-[var(--duration-fast)] ease-out-brand"

Mười ba class nhìn rất rối. Tôi đọc bằng cách xếp chúng vào năm nhóm, theo đúng thứ tự tôi sẽ kiểm một frame trong Figma:

NhómClass trong ví dụNghĩa là
Bố cụcflex items-centerAuto layout ngang, căn giữa theo chiều dọc
Kích thước, khoảng cáchh-9 px-3Cao 36px, padding trái phải 12px
Chữtype-body-sm whitespace-nowrapText style 16px của hệ thống, không xuống dòng
Màu, viền, botext-muted-foreground rounded-mdChữ xám bậc hai, bo góc theo token
Trạng thái, chuyển độnghover:bg-muted hover:text-foreground transition-colors duration-[var(--duration-fast)] ease-out-brandRê chuột thì nền xám, chữ đậm lên, đổi màu trong 120ms

Theo tài liệu Tailwind, thứ tự class trong HTML không quyết định class nào thắng. Bạn cứ đọc theo nhóm, không cần theo thứ tự AI viết.

Class Tailwind thường gặp tương ứng với CSS nào?

Với spacing, Tailwind v4 nhân số trong tên class với biến --spacing, mặc định là 0.25rem (4px). Vậy p-4 là 16px, gap-6 là 24px, h-9 là 36px. Bạn chỉ cần nhớ phép nhân với 4.

ClassCSS sinh raTương đương trong Figma
flexdisplay: flexAuto layout ngang
flex-colflex-direction: columnAuto layout dọc
items-centeralign-items: centerCăn giữa theo trục phụ
justify-betweenjustify-content: space-betweenSpacing mode "Auto"
gap-4gap: calc(var(--spacing) * 4), tức 16pxSpacing between items
p-4, px-3, py-2padding, padding-inline, padding-blockPadding
mt-2margin-top: 8pxKhông có trong auto layout, gần với khoảng trống đặt tay
w-fullwidth: 100%Fill container (theo chiều ngang)
shrink-0flex-shrink: 0Fixed, không bị co lại
min-w-0min-width: 0pxCho phép phần tử co lại để chữ cắt dòng đúng
grid grid-cols-3display: grid và grid-template-columns: repeat(3, minmax(0, 1fr))Lưới 3 cột đều nhau
max-w-3xl mx-automax-width: 48rem và margin-inline: autoKhung nội dung rộng tối đa 768px, căn giữa
relative, absolute inset-0position: relative, position: absolute; inset: 0Ignore auto layout, phủ kín khung cha
sticky top-0position: sticky; top: 0Phần tử dính lại khi cuộn trong prototype
overflow-hiddenoverflow: hiddenClip content
line-clamp-2Cắt chữ sau 2 dòng, thêm dấu ba chấmTruncate text với số dòng tối đa
text-smfont-size: 0.875rem (14px), kèm line-heightCỡ chữ
font-medium, font-semiboldfont-weight: 500, 600Độ đậm
borderborder-width: 1pxStroke 1px
rounded-fullBo tròn hết cỡCorner radius tối đa
hiddendisplay: noneẨn layer

Tôi kiểm từng dòng ở bảng trên bằng cách cho Tailwind 4.3 của repo này biên dịch thử từng class. Riêng rounded-md không nằm trong bảng vì ở site này nó ra 12px, khác giá trị mặc định. Lý do nằm ở mục token bên dưới.

hover:, md:, dark: nghĩa là gì?

Phần đứng trước dấu hai chấm gọi là variant: điều kiện để class phía sau có hiệu lực. Ba nhóm hay gặp nhất:

Trạng thái. hover: áp khi rê chuột. Tailwind v4 bọc nó trong @media (hover: hover), nên nó chỉ có hiệu lực khi thiết bị nhập chính rê được (chuột, trackpad). Trên điện thoại chỉ có cảm ứng, class hover: không được áp. focus-visible: áp khi phần tử được chọn bằng bàn phím. aria-expanded: áp khi thuộc tính aria-expanded="true", ví dụ nút mở menu đang mở. group-hover: cho phép phần tử con đổi kiểu khi rê chuột lên phần tử cha có class group.

Breakpoint. Tailwind viết theo mobile-first. Class không có tiền tố áp cho mọi cỡ màn hình, còn md: nghĩa là từ cỡ md trở lên.

Tiền tốÁp từ chiều rộng
sm:40rem (640px)
md:48rem (768px)
lg:64rem (1024px)
xl:80rem (1280px)
2xl:96rem (1536px)

Vậy w-28 sm:w-44 đọc là: ô ảnh rộng 112px trên điện thoại, từ 640px trở lên thì rộng 176px. Muốn giới hạn ngược lại, dùng max-md: (dưới 768px).

Dark mode. Mặc định, dark: theo cài đặt sáng tối của hệ điều hành. Site này thêm nút chuyển chế độ nên đổi sang theo class, bằng một dòng ở đầu app/globals.css:

@custom-variant dark (&:is(.dark *));

Variant có thể xếp chồng, ví dụ dark:md:hover:bg-muted. Đọc từ trái sang phải: chế độ tối, màn từ 768px, khi rê chuột.

Token nằm ở đâu trong theme?

Tailwind v4 không còn file tailwind.config.js bắt buộc. Token khai báo bằng khối @theme trong CSS. Mỗi biến theo một namespace sẽ sinh ra class: --color-* cho bg-*, text-*, border-*; --radius-* cho rounded-*; --breakpoint-* cho tiền tố responsive.

Site này nối token semantic vào Tailwind như sau (rút gọn):

@theme inline {
  --color-muted: var(--muted);
  --color-muted-foreground: var(--muted-foreground);
  --color-primary-text: var(--primary-text);
  --radius-md: 12px;
}

Nhờ vậy bg-muted biên dịch thành background-color: var(--muted), và khi chế độ tối đổi giá trị --muted, mọi chỗ dùng bg-muted tự đổi theo. Đây là lý do rounded-md ở site này ra 12px. Bài design token là gì giải thích ba lớp token phía sau các biến này.

Khi viết bài này tôi phát hiện một lỗ hổng. Comment trong globals.css ghi rằng không gõ được bg-gray-600, ý là thang xám riêng của site không đưa ra Tailwind. Nhưng file vẫn @import "tailwindcss" đầy đủ và chưa reset bảng màu mặc định, nên bg-gray-600 vẫn biên dịch, ra màu xám mặc định của Tailwind là oklch(44.6% 0.03 256.802). Màu này ám xanh nhẹ, trái với luật thang xám trung tính của site. Tài liệu Tailwind chỉ cách chặn: thêm --color-*: initial; vào @theme để xoá mọi màu mặc định, rồi chỉ khai báo màu của mình.

Class biên dịch được không có nghĩa là class đó thuộc hệ thống của bạn. Muốn biết chắc, hãy đọc khối @theme và kiểm bảng màu mặc định đã bị reset chưa.

Giá trị trong ngoặc vuông có nghĩa là gì?

bg-[#ff009d], p-[13px], text-[22px] là giá trị tuỳ ý: Tailwind sinh class cho đúng giá trị bạn ghi. Cú pháp hợp lệ, nhưng khi đọc diff tôi tìm chúng đầu tiên, vì chúng thường có nghĩa là AI bỏ qua token.

Có một trường hợp tôi giữ: khi bên trong ngoặc là biến của hệ thống. Code của site này viết duration-[var(--duration-fast)]. Tailwind v4 còn có cách viết ngắn hơn cho cùng việc đó là duration-(--duration-fast). Cả hai đều lấy giá trị từ token, nên khi tôi đổi --duration-fast thì mọi chỗ đổi theo.

Làm sao để AI dùng token thay vì giá trị gõ cứng?

Bốn cách tôi dùng, từ nhẹ đến chặt:

  1. Viết luật vào file hướng dẫn. Trong AGENTS.md của repo này có dòng: không hard-code màu hay cỡ trong component, dùng class type-* cho chữ và token màu theo quy ước shadcn. Claude đọc file này mỗi phiên. Cách tổ chức file hướng dẫn nằm ở bài DESIGN.md là gì.
  2. Gọi tên token trong prompt. Thay vì "làm thẻ có nền xám nhạt khi hover", tôi viết "hover dùng bg-muted, không dùng shadow". AI ít đoán hơn khi bạn đưa sẵn tên.
  3. Bắt AI tự rà trước khi bàn giao. Câu tôi hay dùng: "Liệt kê mọi class có ngoặc vuông và mọi mã màu trong các file vừa sửa, giải thích vì sao không dùng token." Bài viết prompt cho Claude có thêm mẫu câu.
  4. Khoá ở tầng theme. Reset bảng màu mặc định bằng --color-*: initial, để class ngoài hệ thống không biên dịch ra màu nào.

Nếu bạn lấy token từ Figma, bài Figma MCP và Claude Code chỉ cách để AI đọc thẳng variable thay vì đoán từ ảnh chụp.

Nên đọc gì tiếp?

Nếu bạn cần một designer đọc được Tailwind trong code của đội mình, phần giới thiệu về tôi có cách liên hệ.

Nguồn

Tài liệu Tailwind ở trên là bản v4, kiểm ngày 04/10/2026. CSS trong bảng class được biên dịch thử bằng Tailwind 4.3.3 của repo này cùng ngày, kể cả trường hợp bg-gray-600.

Câu hỏi thường gặp

Thứ tự class trong chuỗi Tailwind có quan trọng không?
Không ảnh hưởng kết quả. Theo tài liệu Tailwind, khi hai class cùng đặt một thuộc tính, class nằm sau trong file CSS được sinh ra sẽ thắng, bất kể thứ tự bạn viết trong HTML. Vì vậy đừng để hai class mâu thuẫn như flex và grid trên cùng một phần tử.
md: trong Tailwind là màn hình cỡ trung bình thôi phải không?
Không. Tailwind viết theo mobile-first, nên md: nghĩa là từ 48rem (768px) trở lên. Class không có tiền tố áp cho mọi cỡ màn hình. Muốn chỉ áp cho màn hẹp hơn md thì dùng max-md:.
Class có ngoặc vuông như p-[13px] có sai không?
Không sai cú pháp, đó là giá trị tuỳ ý (arbitrary value). Nhưng trong một design system, nó thường là dấu hiệu giá trị nằm ngoài token. Tôi chỉ giữ ngoặc vuông khi bên trong là biến của hệ thống, ví dụ duration-[var(--duration-fast)].
Designer có cần học cấu hình Tailwind không?
Chỉ cần biết token nằm ở đâu. Với Tailwind v4, đó là khối @theme trong file CSS chính. Đọc được khối đó là bạn biết class nào hợp lệ trong hệ thống của mình.