Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 9 — Color Contrast & WCAG Tiêu Chuẩn

Đã đọc 0/14 mục · còn khoảng 12 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Mở đầu — vì sao bài này quan trọng

Hãy tưởng tượng bạn thiết kế một nút "Đặt hàng" màu cam nhạt đặt trên nền trắng. Trên màn hình Retina của chiếc MacBook mới coóng trong văn phòng máy lạnh, nút ấy trông rất "sang". Nhưng khi một cô bác 55 tuổi mở app trên chiếc điện thoại Android hai năm tuổi, giữa trưa nắng gắt ở một quán cà phê vỉa hè Sài Gòn, chữ trên nút gần như biến mất. Cô không nhìn thấy được đâu là nút cần bấm, và đơn hàng không bao giờ được đặt.

Đó chính là vấn đề của color contrast (độ tương phản màu sắc). Đây có lẽ là lỗi accessibility phổ biến nhất trên thế giới — theo báo cáo WebAIM Million (khảo sát 1 triệu trang chủ phổ biến nhất) năm 2024, có tới hơn 81% trang web mắc lỗi tương phản văn bản không đủ. Nói cách khác, cứ 5 trang bạn ghé thăm thì 4 trang có chữ mà một bộ phận người dùng khó hoặc không đọc được.

Điểm hay của color contrast là nó không mơ hồ. Không như nhiều khía cạnh khác của accessibility đôi khi phải tranh luận "thế nào là đủ", tương phản màu là một con số. Bạn đo được, tính được, và biết chính xác mình đạt hay không đạt. Trong bài này, chúng ta sẽ nắm vững các ngưỡng tương phản mà WCAG 2.1 quy định, hiểu cách con số ấy được tính ra, và quan trọng nhất là biết cách kiểm tra cũng như sửa lỗi ngay trong công việc hàng ngày.

Khái niệm cốt lõi

Contrast ratio là gì

Contrast ratio (tỉ lệ tương phản) là con số mô tả độ chênh lệch về độ sáng giữa hai màu — thường là màu chữ (foreground) và màu nền (background). Nó được biểu diễn dưới dạng tỉ lệ, ví dụ 4.5:1 hoặc 7:1.

Giá trị này dao động từ 1:1 (hai màu giống hệt nhau, hoàn toàn không phân biệt được) đến 21:1 (đây là mức tối đa, tương ứng chữ đen tuyền trên nền trắng tinh hoặc ngược lại). Con số càng cao thì chữ càng nổi bật, càng dễ đọc.

Điều nhiều bạn hiểu nhầm: contrast ratio không phụ thuộc vào việc màu nào "đậm" màu nào "nhạt" theo cảm nhận thông thường, mà dựa trên relative luminance — độ sáng tương đối được tính theo cách mắt người cảm nhận. Mắt người nhạy với màu xanh lá hơn màu xanh dương và đỏ, nên công thức tính luminance cho mỗi kênh màu một trọng số khác nhau. Cụ thể, luminance được tính xấp xỉ theo tỉ trọng: khoảng 21% từ kênh đỏ, 72% từ kênh xanh lá, và 7% từ kênh xanh dương.

Đây là lý do khiến nhiều designer bất ngờ: một chữ vàng tươi trên nền trắng có contrast ratio rất thấp (thường dưới 2:1) và gần như không đọc được, dù cảm giác vàng là màu "nổi". Ngược lại, chữ xanh dương đậm trên nền trắng lại đạt tương phản rất tốt. Vàng chứa nhiều thành phần xanh lá và đỏ — hai kênh sáng nhất — nên luminance của nó cao, gần với nền trắng.

Bảng tiêu chuẩn WCAG 2.1

Đây là phần bạn cần thuộc nằm lòng. WCAG 2.1 chia ra hai mức: AA (mức tối thiểu, là mục tiêu của hầu hết dự án và cũng là mức luật pháp nhiều nước yêu cầu) và AAA (mức nâng cao).

MứcVăn bản thườngVăn bản lớnThành phần UI & đồ họa
AA4.5:13:13:1
AAA7:14.5:1(không quy định riêng)
Ba khái niệm cần làm rõ:

Văn bản thường (normal text): mọi văn bản có kích thước nhỏ hơn ngưỡng "lớn". Đây là phần lớn chữ trên trang: đoạn văn, nhãn, chú thích.

Văn bản lớn (large text): được định nghĩa là chữ từ 18pt (khoảng 24px) trở lên, hoặc chữ 14pt (khoảng 18.66px) trở lên nếu in đậm (bold). Chữ lớn được nới lỏng ngưỡng vì nét chữ dày hơn, dễ đọc hơn dù tương phản thấp hơn một chút.

Thành phần UI & đồ họa (non-text contrast): đây là điểm mới quan trọng của WCAG 2.1 so với 2.0 (tiêu chí 1.4.11). Nó yêu cầu các thành phần giao diện cần thiết để nhận biết — ví dụ viền của ô input, biểu tượng, đường ranh giới của nút, chỉ báo focus, các phần của biểu đồ — phải đạt tối thiểu 3:1 so với màu xung quanh. Nếu ô input của bạn chỉ có viền xám nhạt trên nền trắng, người dùng thị lực kém có thể không thấy ô đâu để điền.

Vì sao là 4.5:1 mà không phải con số khác

Con số 4.5:1 không phải ngẫu nhiên. WCAG dựa trên nghiên cứu về thị lực: mức này được tính để một người có thị lực khoảng 20/40 (tương đương suy giảm thị lực nhẹ đến vừa, rất phổ biến ở người trên 45–50 tuổi do lão hóa) vẫn đọc được thoải mái. Mức AAA 7:1 nhắm tới người có thị lực khoảng 20/80 — suy giảm nặng hơn.

Điều này đặc biệt đáng lưu tâm với thị trường Việt Nam, nơi dân số đang già hóa nhanh. Presbyopia (lão thị) và suy giảm độ nhạy tương phản là hiện tượng gần như ai cũng gặp sau tuổi 40. Thiết kế đạt chuẩn tương phản không chỉ phục vụ "người khuyết tật" theo nghĩa hẹp, mà phục vụ chính bố mẹ, ông bà, và cả bản thân bạn trong tương lai.

Những trường hợp được miễn trừ

WCAG có vài ngoại lệ hợp lý. Bạn không bắt buộc phải đạt ngưỡng tương phản với:

  • Văn bản trang trí không mang thông tin gì (ví dụ chữ mờ làm nền).
  • Logo hoặc tên thương hiệu — vì đó là tài sản nhận diện, không thể ép đổi màu.
  • Văn bản trong ảnh chụp khi chữ chỉ là một phần tình cờ của bức ảnh (ví dụ biển hiệu trong ảnh đường phố).
  • Thành phần đang ở trạng thái disabled (bị vô hiệu hóa) cũng được miễn.
Nhưng hãy cẩn thận: đừng lạm dụng ngoại lệ. Nhiều người viện cớ "đây là brand color" để né tránh, trong khi màu thương hiệu hoàn toàn có thể dùng ở vai trò khác (nền lớn, viền) thay vì làm màu chữ nhỏ.

Tình huống thực tế

Ví dụ 1 — Nút CTA "tàng hình" của một sàn thương mại điện tử

Một startup thương mại điện tử tại TP.HCM (tạm gọi là ShopViet) làm chiến dịch flash sale. Team thiết kế chọn màu chủ đạo là cam pastel #F7A072 cho nút "Mua ngay", với chữ trắng #FFFFFF bên trên. Trên Figma nhìn rất mềm mại, đúng "vibe" mùa hè.

Khi đo lại, contrast ratio giữa trắng và cam pastel này chỉ đạt khoảng 1.9:1 — thấp hơn rất xa ngưỡng 4.5:1. Đội marketing phát hiện tỉ lệ nhấp vào nút trên mobile thấp bất thường. Sau khi làm A/B test, họ đổi màu nút sang cam đậm hơn #D9531E (giữ nguyên tông thương hiệu nhưng tối hơn), nâng contrast lên khoảng 4.6:1. Kết quả: tỉ lệ chuyển đổi trên mobile tăng rõ rệt, đặc biệt ở nhóm người dùng lớn tuổi.

Bài học: Tương phản kém không chỉ là chuyện "tuân thủ luật" — nó ảnh hưởng trực tiếp đến doanh thu. Một nút mà một phần khách hàng không nhìn rõ thì đó là tiền bị bỏ lại trên bàn.

Ví dụ 2 — Placeholder xám thay cho nhãn thật ở một app ngân hàng

Một ngân hàng số ở Đông Nam Á thiết kế form mở tài khoản theo phong cách tối giản: bỏ hết nhãn (label), chỉ dùng placeholder màu xám nhạt #BBBBBB trên nền trắng để hướng dẫn "Nhập số CMND/CCCD". Contrast của placeholder này chỉ khoảng 1.6:1.

Vấn đề kép: thứ nhất, placeholder mờ đến mức người dùng thị lực yếu không đọc được yêu cầu; thứ hai, khi họ bắt đầu gõ, placeholder biến mất và họ quên mất ô này để làm gì. Bộ phận hỗ trợ khách hàng nhận hàng loạt cuộc gọi than phiền "không biết điền gì vào ô trống". Đội sản phẩm phải làm lại: đưa nhãn thật lên trên ô, dùng màu #333333 (contrast trên 12:1), và giữ placeholder chỉ như ví dụ phụ với màu đậm hơn.

Bài học: Placeholder xám nhạt là một trong những "cái bẫy thẩm mỹ" phổ biến nhất. Nó nhìn "sạch" nhưng vi phạm cả tương phản lẫn khả năng ghi nhớ. Với thông tin quan trọng như biểu mẫu ngân hàng, tương phản kém không chỉ gây khó chịu mà có thể khiến người dùng nhập sai thông tin nhạy cảm.

Ví dụ 3 — Biểu đồ dashboard chỉ phân biệt bằng sắc độ nhạt

Một công ty SaaS làm dashboard phân tích. Biểu đồ đường có ba đường: xanh dương đậm, xanh dương vừa và xanh dương nhạt, tất cả trên nền trắng. Đường nhạt nhất #A9C7E8 chỉ đạt contrast khoảng 1.8:1 so với nền — không đạt ngưỡng 3:1 dành cho đồ họa mang thông tin.

Người dùng phản hồi rằng trên máy chiếu trong phòng họp sáng, đường nhạt gần như biến mất, khiến việc trình bày số liệu trở nên khó khăn. Đội thiết kế nâng độ đậm của các đường lên để mỗi đường đều đạt tối thiểu 3:1 so với nền, và tăng độ dày nét vẽ.

Bài học: Tiêu chí non-text contrast (3:1) áp dụng cho cả biểu đồ, icon, và đường ranh giới — không chỉ riêng chữ. Dữ liệu trực quan mà không nhìn thấy được thì vô nghĩa.

Hướng dẫn từng bước

Đây là quy trình thực tế để kiểm tra và đảm bảo tương phản trong dự án:

Bước 1 — Xác định cặp màu cần kiểm tra. Với mỗi thành phần, hỏi rõ: màu chữ là gì, nằm trên nền màu gì? Lưu ý nền thật sự chứ không phải nền lý thuyết — nếu chữ nằm trên ảnh hoặc gradient, bạn phải kiểm tra ở điểm nền sáng nhất và tối nhất.

Bước 2 — Đo contrast ratio. Dùng công cụ chuyên dụng. Một số lựa chọn miễn phí phổ biến:

  • WebAIM Contrast Checker (webaim.org/resources/contrastchecker) — dán hai mã màu hex vào là ra kết quả kèm dấu pass/fail cho từng mức.
  • Trình chọn màu trong Chrome DevTools — khi bạn inspect một phần tử chữ, phần color picker hiển thị luôn contrast ratio và gạch đường tham chiếu ngưỡng AA/AAA.
  • Plugin Figma như "Contrast" hoặc "Stark" để kiểm ngay trong lúc thiết kế.
Bước 3 — Xác định ngưỡng cần đạt. Chữ này là normal hay large? Nếu là thành phần UI (viền, icon) thì áp ngưỡng 3:1. Dự án của bạn nhắm mức AA hay AAA?

Bước 4 — So sánh và điều chỉnh nếu chưa đạt. Nếu thiếu, bạn có ba hướng: làm màu chữ đậm hơn, làm màu nền tương phản hơn, hoặc tăng kích thước/độ đậm chữ để chuyển sang ngưỡng "large text" nới lỏng hơn. Mẹo thực dụng: khi cần giữ đúng màu thương hiệu, thường dễ nhất là điều chỉnh độ sáng (lightness) trong không gian màu HSL — kéo lightness xuống một chút thường đủ đưa màu qua ngưỡng mà mắt thường khó nhận ra sự thay đổi.

Bước 5 — Kiểm tra cả các trạng thái. Đừng chỉ kiểm trạng thái mặc định. Kiểm cả hover, focus, active, disabled, và cả dark mode nếu có. Rất nhiều lỗi tương phản ẩn nấp ở trạng thái hover hoặc ở giao diện tối mà không ai để ý.

Bước 6 — Ghi lại vào design system. Khi đã có cặp màu đạt chuẩn, đưa chúng thành token màu (color token) trong hệ thống thiết kế để cả team dùng lại, tránh mỗi người tự chọn màu và tái phạm lỗi cũ.

Lỗi thường gặp & mẹo

Lỗi 1 — Nhầm "đậm/nhạt cảm quan" với luminance thật. Như đã nói, vàng, cam nhạt, xanh mint nhìn có vẻ nổi nhưng luminance rất cao, tương phản với nền trắng cực thấp. Đừng tin mắt, hãy tin công cụ đo.

Lỗi 2 — Chỉ kiểm tra trên màn hình xịn, môi trường lý tưởng. Màn hình văn phòng độ sáng cao che giấu rất nhiều lỗi. Mẹo: thỉnh thoảng giảm độ sáng màn hình xuống 40%, hoặc mang laptop ra chỗ có ánh sáng mạnh để trải nghiệm như người dùng thật.

Lỗi 3 — Quên chữ nằm trên ảnh và gradient. Chữ trắng đặt trên ảnh banner rất hay lỗi vì có vùng ảnh sáng làm chữ chìm. Mẹo: thêm một lớp phủ (overlay) tối bán trong suốt giữa ảnh và chữ, hoặc thêm bóng đổ (text-shadow), hoặc đặt chữ trong một khối nền màu đặc.

Lỗi 4 — Chỉ dùng màu để truyền thông tin. Đây là chủ đề riêng của bài sau về color blindness, nhưng cần nhớ ngay: tương phản đủ không có nghĩa là được phép dùng "chỉ màu đỏ = lỗi, chỉ màu xanh = đúng". Đó là câu chuyện khác, sẽ bàn kỹ ở Bài 10.

Lỗi 5 — Bỏ quên chỉ báo focus. Đường viền focus mờ nhạt vi phạm ngưỡng 3:1 là lỗi rất phổ biến. Chi tiết về focus indicator sẽ được nói kỹ ở Bài 12, nhưng hãy nhớ nó cũng phải đạt tương phản.

Mẹo tổng quát: Đặt ngưỡng nội bộ cao hơn chuẩn một chút. Nếu bạn nhắm AA (4.5:1), hãy cố đạt khoảng 5:1 trở lên để có "khoảng an toàn", phòng khi màu bị lệch nhẹ do màn hình, do nén ảnh, hay do ai đó chỉnh token sau này.

Bài tập thực hành

  • Đo và phân loại. Lấy ba cặp màu sau, dùng WebAIM Contrast Checker để đo và ghi lại contrast ratio, rồi kết luận mỗi cặp pass/fail ở mức AA cho văn bản thường:
- Chữ #767676 trên nền #FFFFFF - Chữ #FFFFFF trên nền #F7A072 - Chữ #1A1A2E trên nền #EEEEEE

  • Sửa lỗi thực tế. Mở một trang web bạn thường dùng (hoặc chính dự án của bạn). Bật Chrome DevTools, inspect ít nhất 5 phần tử chữ khác nhau và ghi lại contrast ratio. Tìm ít nhất một phần tử không đạt AA, sau đó thử đề xuất một mã màu mới đạt chuẩn mà vẫn giữ được tinh thần thiết kế ban đầu (gợi ý: chỉ chỉnh lightness trong HSL).
  • Kiểm non-text. Tìm một biểu mẫu bất kỳ trên web, kiểm tra viền của các ô input xem có đạt 3:1 so với nền không. Nếu không, thử đề xuất màu viền đạt chuẩn.
  • Thử thách môi trường. Giảm độ sáng màn hình xuống mức thấp nhất bạn còn chịu được, rồi mở lại giao diện bạn đang làm. Ghi lại những chỗ chữ trở nên khó đọc — đó chính là các điểm tương phản yếu cần ưu tiên sửa.

Tóm tắt

Color contrast là một trong những trụ cột dễ đo lường và dễ sửa nhất của accessibility, nhưng lại bị vi phạm nhiều nhất. Những điểm cốt lõi cần nhớ:

  • Contrast ratio dao động từ 1:1 đến 21:1, dựa trên relative luminance (độ sáng tương đối) chứ không phải cảm nhận "đậm/nhạt".
  • Chuẩn WCAG 2.1 mức AA: văn bản thường cần 4.5:1, văn bản lớn (từ 18pt, hoặc 14pt bold) cần 3:1, và thành phần UI/đồ họa mang thông tin cũng cần 3:1.
  • Mức AAA nâng ngưỡng lên 7:1 (thường) và 4.5:1 (lớn), phục vụ người suy giảm thị lực nặng hơn.
  • Có ngoại lệ cho logo, chữ trang trí, và thành phần disabled — nhưng đừng lạm dụng.
  • Luôn kiểm tra bằng công cụ đo (WebAIM, DevTools, plugin Figma), kiểm cả các trạng thái và dark mode, và đưa cặp màu đạt chuẩn vào design token để tái sử dụng.
Đạt chuẩn tương phản không phải là gò bó sáng tạo — đó là làm cho thiết kế của bạn hoạt động được với nhiều người hơn, trong nhiều hoàn cảnh hơn, kể cả bố mẹ bạn dưới ánh nắng vỉa hè. Ở bài tiếp theo, chúng ta sẽ đi sâu vào một vấn đề liên quan chặt chẽ: color blindness và nguyên tắc không phụ thuộc hoàn toàn vào màu sắc để truyền tải thông tin.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi