Contrast accessibility cơ bản | Chữ xám, placeholder và checklist UI hàng ngày【2026】

(Cập nhật: 19 tháng 7, 2026 ) accessibility độ tương phản WCAG contrast UI frontend
Kết luận

Contrast accessibility cơ bản = đo chữ/nền bằng số, không bằng mắt trên Figma sáng. Mục tiêu hàng ngày là WCAG AA 4.5:1 cho chữ thường. Chữ xám “sang” (gray-400), placeholder thay label, và link pastel là ba lỗi junior hay merge. Đo nhanh bằng công cụ kiểm tra độ tương phản trước khi mở PR.

Bài WCAG sâu về chữ trên ảnh hero dành cho landing và brand. Bài này ngược lại: contrast a11y cơ bản — những cặp màu bạn đụng mỗi ngày trong form, bảng, card, dashboard outsourcing.

Junior Việt thường nhận ticket “làm UI giống Figma”. Figma trên Mac Retina trong văn phòng điều hòa nhìn ổn; khách mở trên điện thoại ngoài đường Nguyễn Huệ thì helper text biến thành sương. Reviewer bảo “chữ mờ” — bạn không biết bắt đầu từ đâu vì không có số.

Ai nên đọc

  • Fresher / intern lần đầu nghe “WCAG” trong PR comment
  • Freelancer bàn giao admin CRUD, form đăng ký, bảng dữ liệu
  • Designer–dev handoff khi token chỉ có text-muted mà không ghi contrast

Contrast accessibility là gì (phiên bản 5 phút)

Độ tương phản (contrast ratio) so sánh độ sáng tương đối của hai màu. Công thức WCAG rút gọn: (L1 + 0.05) / (L2 + 0.05). Trắng/đen = 21:1; hai màu giống nhau = 1:1.

Bạn không cần tự tính tay. Cần nhớ ngưỡng quyết định:

Ngưỡng nhớ thuộc cho UI hàng ngày
Loại AA (mục tiêu) Ghi chú thực tế
Chữ thường (body, label, error) ≥ 4.5:1 Hầu hết product đặt đây làm cổng QA
Chữ lớn (≥ ~24px hoặc ~18.66px bold) ≥ 3:1 Heading lớn; đừng dùng cho caption 12px
UI không phải chữ (viền, icon nghĩa) ≥ 3:1 Viền input, focus ring có nghĩa

AAA 7:1 hữu ích cho nội dung pháp lý / giáo dục, nhưng không phải mục tiêu mặc định của mọi secondary text. Ép AAA trên mọi text-muted thường khiến UI thành đen–trắng cứng.


Ba lỗi contrast junior hay merge

1) Secondary text = gray-400

Tailwind text-gray-400 (#9CA3AF) trên bg-white trông “hierarchy đẹp” trên mock sáng. Số liệu thực tế:

#9CA3AF trên #FFFFFF  →  ~2.54:1  →  Fail AA (chữ thường)
#6B7280 trên #FFFFFF  →  ~4.83:1  →  Pass AA   (gray-500)
#4B5563 trên #FFFFFF  →  ~7.0:1   →  Pass AA/AAA gần biên

Quy tắc tay: chữ phụ vẫn phải đọc được như câu đầy đủ — không chỉ “trang trí hierarchy”. Nếu nội dung quan trọng (ngày hết hạn, số dư, trạng thái đơn), dùng shade đạt ≥ 4.5:1.

2) Placeholder thay cho label

<!-- Fail UX + rủi ro a11y -->
<input type="email" placeholder="Email của bạn" />

<!-- Đúng hướng -->
<label for="email">Email</label>
<input id="email" type="email" placeholder="vd: [email protected]" />

Placeholder biến mất khi gõ; màu thường cố ý nhạt. Đừng lấy màu placeholder làm chuẩn cho label. Label Pass AA; placeholder chỉ gợi ý format.

Brand #60A5FA (blue-400) trên trắng có thể Fail hoặc sát biên tùy ngữ cảnh. Text link dài trong đoạn văn cần đo như chữ thường. Nút filled: đo chữ trên nền nút, không đo logo trên slide marketing.


Case study: form đăng ký 1 buổi chiều

Bối cảnh: Intern làm form đăng ký khóa học. Figma dùng text-slate-400 cho mọi hint.

Phần tửCặp màu ban đầuKết quả đoSửa
Label “Họ tên”#94A3B8 / #FFF~2.8:1 Fail#334155 (slate-700)
Hint “Như trên CCCD”#CBD5E1 / #FFF~1.6:1 FailGộp vào helper dưới field, #475569
Link “Điều khoản”#93C5FD / #FFF~2.2:1 Fail#1D4ED8 hoặc underline + màu Pass
Error “Bắt buộc”#FCA5A5 / #FFF~2.0:1 Fail#B91C1C trên nền trắng

Sau khi đổi token, lead không còn comment “chữ mờ”; QA chỉ còn check logic validate.


Checklist đo trong 10 phút

  1. Mở trang trên Chrome, DevTools → chọn chữ → xem colorbackground-color computed (cẩn thận nested opacity).
  2. Mở Color Contrast Checker — chọn màu chữ (foreground) và màu nền (background).
  3. Đọc tỷ lệ và trạng thái AA chữ thường / AA chữ lớn / AAA.
  4. Với nút: đo riêng default và :hover nếu đổi màu.
  5. Với dark mode: đo lại trên nền tối — Pass light không tự Pass dark.

Công cụ chạy trên trình duyệt, không cần tài khoản — phù hợp log màu nội bộ và token chưa public.

Ví dụ nhanh trên tool:
Màu chữ: #374151
Màu nền: #FFFFFF
→ Tỷ lệ cao, Pass AA chữ thường
Đổi chữ sang #9CA3AF → Fail ngay — đúng “bẫy gray-400”

Phân biệt nhanh với bài WCAG sâu

Hai góc contrast trên Kawa Blog
Bài này (cơ bản) Bài WCAG landing
Form, bảng, admin, text UI hàng ngày Chữ trên ảnh hero / campaign
Token gray, placeholder, link, error Overlay ảnh, brand pastel, AA vs AAA chiến lược
Checklist PR 10 phút Checklist trước launch landing SME

Đọc thêm khi làm hero: Kiểm tra độ tương phản WCAG AA/AAA.


Lỗi thường gặp sau khi “đã Pass tool”

  • opacity trên cả khối: Tool Pass HEX gốc, nhưng opacity: 0.5 trên wrapper làm chữ lẫn nền — đo màu sau khi flatten hoặc tránh opacity trên text.
  • rgba overlay: Nền hiệu dụng ≠ HEX ảnh gốc. Lấy màu vùng chữ thật.
  • Anti-alias / font mỏng: 4.51:1 trên Inter 300 có thể vẫn khó đọc — tăng weight hoặc shade đậm hơn một bậc.
  • Chỉ test trên màn Mac: Thêm một lần nhìn trên điện thoại ngoài trời trước demo khách.

Checklist dán vào PR (copy được)

  • Body / label / error ≥ 4.5:1
  • Secondary text quan trọng ≥ 4.5:1 (không dùng gray-400 mặc định)
  • Mọi input có <label> visible; placeholder không thay label
  • Link trong đoạn văn Pass AA
  • Viền input / focus đủ ~3:1 nếu là chỉ báo duy nhất
  • Đã đo bằng công cụ contrast và ghi cặp HEX trong PR nếu đổi token

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

Chỉ dùng màu hệ thống OS có cần đo không?
Vẫn nên đo token trong design system của bạn. Màu hệ thống không bảo vệ cặp text-muted tự chế.

Disabled button Fail AA có sao không?
Trạng thái disabled thường được chấp nhận mờ hơn; đừng dùng cùng xám đó cho thông báo lỗi hoặc giá tiền.

Có cần axe/lighthouse mỗi PR không?
Nên có trong CI dần. Contrast tay bằng tool vẫn bắt được sớm hơn khi mới chọn màu ở Figma/CSS.

Liên kết liên quan