Mở đầu — vì sao bài này quan trọng
Hãy hình dung thế này: bạn vừa ship một feature đặt lịch hẹn mới, demo chạy mượt, designer khen đẹp, sếp gật gù. Ba tuần sau, bộ phận Customer Support chuyển lên một email từ một khách hàng khiếm thị. Anh ấy dùng trình đọc màn hình (screen reader) và không thể nào hoàn tất việc đặt lịch, vì cái nút "Xác nhận" của bạn chỉ là một <div> được tô màu xanh, không có nhãn, không bấm được bằng bàn phím. Với anh ấy, feature của bạn đơn giản là không tồn tại.
Đó chính là lý do accessibility — viết tắt là a11y (chữ "a", 11 ký tự ở giữa, rồi chữ "y") — phải xuất hiện trong PRD/Spec của bạn, chứ không phải là thứ "để sau khi xong việc thì làm".
Trong các bài trước, bạn đã học cách viết Problem, Goals, user stories, acceptance criteria, và mô tả các trạng thái empty/loading/error. Bài này tập trung vào một lát cắt rất cụ thể nhưng thường bị bỏ quên: làm sao để spec của bạn đảm bảo sản phẩm dùng được cho người khuyết tật, và làm sao biến yêu cầu a11y thành những dòng acceptance criteria mà engineer có thể build và QA có thể kiểm tra.
Đây không phải chủ đề "đạo đức nghề nghiệp" mơ hồ. Nó là yêu cầu pháp lý, là quyết định thương mại, và là dấu hiệu của một PM trưởng thành. Một PM viết a11y vào spec ngay từ đầu sẽ tiết kiệm cho team hàng tuần làm lại (rework) về sau, và tránh cho công ty những rủi ro kiện tụng tốn kém.
Khái niệm cốt lõi
A11y là gì và tại sao PM phải quan tâm
Accessibility nghĩa là sản phẩm dùng được cho tất cả mọi người, bao gồm người có khiếm khuyết về thị giác (mù, kém thị lực, mù màu), thính giác (điếc, nghe kém), vận động (không dùng được chuột, run tay), và nhận thức (khó tập trung, khó đọc).
Có ba lý do để bạn — với tư cách PM — đưa a11y vào spec:
1. Pháp lý (Legal). Ở Mỹ, đạo luật ADA (Americans with Disabilities Act) đã được toà án diễn giải áp dụng cho cả website và app; mỗi năm có hàng nghìn vụ kiện. Ở châu Âu, European Accessibility Act (EAA) bắt đầu có hiệu lực bắt buộc từ tháng 6/2025, áp dụng cho nhiều sản phẩm số bán vào thị trường EU — bao gồm cả các công ty Việt Nam/Đông Nam Á bán phần mềm, app, hay dịch vụ ecommerce cho khách EU. Nếu sản phẩm của bạn có người dùng quốc tế, đây không còn là chuyện "nice to have".
2. Thương hiệu & thị trường (Brand & market). Khoảng 15% dân số thế giới sống chung với một dạng khuyết tật nào đó — tức hơn 1 tỷ người. Đó là một thị phần khổng lồ bạn đang vô tình loại bỏ. Chưa kể a11y tốt còn phục vụ cả những người "tạm thời khuyết tật": người gãy tay dùng một tay, người đứng ngoài nắng nhìn màn hình chói, người đang bế con nên chỉ thao tác được bằng giọng nói.
3. Chất lượng code (Code quality). Đây là lợi ích ít người nói tới. Một sản phẩm được build đúng chuẩn a11y thường có HTML ngữ nghĩa (semantic HTML) sạch sẽ — dùng <button>, <nav>, <label> đúng vai trò thay vì nhồi nhét <div>. Code như vậy dễ test bằng automation hơn, SEO tốt hơn, và ít bug hơn. A11y tốt và kỹ thuật tốt thường đi cùng nhau.
WCAG — bộ tiêu chuẩn bạn cần biết tên
Chuẩn quốc tế cho a11y là WCAG (Web Content Accessibility Guidelines). Bạn không cần thuộc lòng, nhưng cần biết bộ khung của nó để viết spec có căn cứ. WCAG xoay quanh bốn nguyên tắc, gọi tắt là POUR:
- Perceivable (Cảm nhận được): người dùng phải nhận biết được nội dung. Ví dụ: ảnh phải có text thay thế (alt text), video phải có phụ đề.
- Operable (Thao tác được): mọi chức năng phải dùng được bằng bàn phím, không bắt buộc phải dùng chuột.
- Understandable (Hiểu được): giao diện và thông báo lỗi phải rõ ràng, dễ đoán.
- Robust (Bền vững): nội dung phải hoạt động tốt với các công nghệ hỗ trợ như screen reader.
Những "đầu mục a11y" cần xuất hiện trong spec
Để cụ thể hoá, đây là những hạng mục bạn nên cân nhắc đưa vào mỗi spec có giao diện:
- Keyboard navigation: dùng phím Tab di chuyển qua mọi phần tử tương tác theo thứ tự hợp lý; Enter/Space để kích hoạt.
- Focus state: phần tử đang được chọn phải có viền/đánh dấu nhìn thấy rõ.
- Screen reader labels: mỗi nút, ô nhập, icon phải có nhãn để screen reader đọc lên (qua
aria-labelhoặc text liên kết). - Color contrast: độ tương phản giữa chữ và nền tối thiểu 4.5:1 cho chữ thường (chuẩn AA).
- Không chỉ dựa vào màu sắc: đừng để màu đỏ là dấu hiệu lỗi duy nhất — phải kèm icon hoặc chữ.
- Touch target size: vùng bấm tối thiểu khoảng 44x44 pixel để người run tay vẫn bấm trúng.
- Alt text cho hình ảnh và caption cho video/audio.
- Tôn trọng cài đặt hệ thống: ví dụ "Reduce Motion" (giảm hiệu ứng động) cho người bị say chuyển động.
Tình huống thực tế
Ví dụ 1 — Sàn thương mại điện tử Việt Nam và nút "Mua ngay" vô hình
Một sàn TMĐT lớn tại Việt Nam (tạm gọi là ShopViet) tung ra trang chi tiết sản phẩm mới. Nút "Mua ngay" được designer làm rất bắt mắt: chữ trắng trên nền gradient cam-vàng nhạt. Đẹp trên Figma, nhưng độ tương phản chỉ đạt 2.1:1 — thấp hơn nhiều so với chuẩn AA 4.5:1.
Hệ quả: nhóm khách lớn tuổi (40+) và người kém thị lực — vốn là tệp khách chi tiêu mạnh — khó đọc được chữ trên nút. Team không có dữ liệu trực tiếp về việc này, nhưng khi một bạn QA tình cờ test bằng công cụ kiểm tra contrast, họ phát hiện vấn đề. Sửa lại màu nút, tỷ lệ click vào "Mua ngay" trên trang đó tăng khoảng 6% trong A/B test — không phải nhờ thiết kế "đẹp hơn", mà chỉ vì nhiều người đọc được nó.
Bài học: một dòng acceptance criteria đơn giản trong spec — "Tất cả text trên CTA phải đạt contrast ≥ 4.5:1" — đã có thể chặn lỗi này từ khâu design review, trước khi tốn công A/B test để phát hiện.
Ví dụ 2 — Startup fintech và rủi ro pháp lý từ thị trường EU
Một startup fintech ở Đông Nam Á (tạm gọi PayMango) xây app chuyển tiền, và bắt đầu mở rộng phục vụ kiều bào tại châu Âu. Đội pháp chế cảnh báo: từ tháng 6/2025, European Accessibility Act yêu cầu các dịch vụ tài chính số bán cho người tiêu dùng EU phải đạt chuẩn a11y, nếu không có thể bị phạt và cấm cung cấp dịch vụ.
Lúc này PM mới giật mình: toàn bộ luồng KYC (xác minh danh tính) của app dùng các icon trạng thái mà screen reader không đọc được, và quy trình nhập OTP không thao tác được bằng bàn phím trên web. Việc retrofit — làm lại a11y cho một sản phẩm đã build xong — tốn của họ gần hai sprint (4 tuần) và phải kéo cả designer lẫn 3 engineer vào.
PM rút kinh nghiệm: ở các feature sau, ngay trong phần Goals của PRD, anh thêm dòng "Non-goal: chưa hỗ trợ AAA, nhưng AA là bắt buộc cho mọi luồng liên quan giao dịch tiền." và đưa một mục "Accessibility requirements" cố định vào template PRD của team.
Bài học: a11y rẻ khi làm sớm, đắt khi làm muộn. Đưa nó vào spec từ đầu không chỉ là chuyện đạo đức — nó là quản trị rủi ro pháp lý và chi phí.
Ví dụ 3 — App học trực tuyến và người dùng dùng một tay
Một nền tảng học trực tuyến (giả định) làm tính năng quiz có thanh trượt (slider) để chọn mức độ tự tin sau mỗi câu hỏi. Slider rất "xịn" về tương tác kéo-thả, nhưng chỉ kéo được bằng chuột hoặc vuốt ngón tay chính xác.
Một học viên bị liệt nhẹ vận động tay phản hồi rằng anh không dùng được tính năng này — anh điều hướng app chủ yếu bằng bàn phím. Team kiểm tra và nhận ra slider hoàn toàn không nhận phím mũi tên trái/phải, và không thể Tab tới được.
Cách sửa đúng theo spec a11y: slider phải (1) focus được bằng Tab, (2) tăng/giảm giá trị bằng phím mũi tên, (3) có nhãn screen reader đọc ra giá trị hiện tại, và (4) kèm một input số để người dùng nhập tay thay vì bắt buộc kéo.
Bài học: "Operable" trong WCAG nghĩa là mọi thứ làm được bằng chuột cũng phải làm được bằng bàn phím. Bất cứ tương tác kéo-thả, hover, hay cử chỉ phức tạp nào trong spec đều cần một dòng mô tả "phương án bàn phím tương đương".
Hướng dẫn từng bước
Đây là quy trình bạn có thể áp dụng để đưa a11y vào spec một cách có hệ thống.
Bước 1 — Thêm một mục "Accessibility" cố định vào template PRD. Đừng để a11y phụ thuộc trí nhớ. Hãy có một heading cố định, ngay cạnh các mục như "Edge cases" hay "Analytics". Nếu feature không có giao diện (ví dụ một thay đổi backend thuần), bạn vẫn ghi rõ "N/A — không có UI" để chứng minh bạn đã cân nhắc.
Bước 2 — Tuyên bố mức tuân thủ. Viết rõ một câu: "Feature này phải đạt WCAG 2.1 mức AA." Câu này tạo ra một "đường biên" chung mà cả design, eng và QA cùng hiểu.
Bước 3 — Rà từng tương tác trong feature theo checklist POUR. Với mỗi màn hình/component, tự hỏi:
- Người dùng screen reader có nghe được nội dung và nhãn không? (Perceivable)
- Người dùng bàn phím có thao tác được mọi nút không? (Operable)
- Thông báo lỗi có rõ ràng, có dựa vào màu duy nhất không? (Understandable)
- Có dùng đúng component chuẩn để screen reader hiểu không? (Robust)
- "Người dùng có thể hoàn tất luồng đặt lịch chỉ bằng bàn phím (Tab + Enter), không cần chuột."
- "Mọi icon-only button có
aria-labelmô tả hành động." - "Thông báo lỗi form hiển thị bằng cả chữ và icon, không chỉ màu đỏ."
- "Khi mở modal, focus tự động chuyển vào modal và bị giữ trong đó (focus trap) cho tới khi đóng."
Bước 6 — Liên kết với Design review. A11y một phần là trách nhiệm của design (màu sắc, contrast, thứ tự đọc, kích thước vùng bấm). Hãy đảm bảo mock đã được kiểm tra contrast trước khi đưa cho eng. Việc này nối tiếp sang bài "Design Review Process" ở sau khoá.
Lỗi thường gặp & mẹo
Lỗi 1 — Coi a11y là việc "để sau". Đây là lỗi đắt nhất. Như ví dụ PayMango, retrofit tốn gấp nhiều lần. Mẹo: đưa a11y thành một dòng trong "Definition of Done" của mọi feature có UI.
Lỗi 2 — Viết yêu cầu mơ hồ. "Phải accessible" là vô nghĩa với engineer. Mẹo: luôn quy về hành động kiểm tra được — "Tab tới được", "screen reader đọc ra X", "contrast ≥ 4.5:1".
Lỗi 3 — Chỉ dựa vào màu sắc để truyền tải thông tin. Trạng thái "thành công/thất bại" mà chỉ phân biệt bằng xanh/đỏ sẽ vô hình với ~8% nam giới bị mù màu. Mẹo: luôn kèm icon hoặc text bên cạnh màu.
Lỗi 4 — Dùng <div> thay cho phần tử chuẩn. Một <div onClick> trông giống nút nhưng screen reader không biết đó là nút, và không Tab tới được. Mẹo: trong spec, ghi rõ "dùng phần tử button/link ngữ nghĩa, không phải div tạo kiểu".
Lỗi 5 — Quên các tương tác phi-chuột. Hover-to-reveal, kéo-thả, vuốt — những thứ này thường bỏ quên người dùng bàn phím. Mẹo: với mỗi cử chỉ chuột/cảm ứng, hỏi "phương án bàn phím là gì?".
Lỗi 6 — Bỏ quên alt text động. Ảnh do người dùng upload hay icon trạng thái thay đổi cần quy tắc rõ ràng cho alt text. Mẹo: spec hoá luôn — ví dụ "ảnh sản phẩm dùng tên sản phẩm làm alt text".
Mẹo vàng: bạn không cần là chuyên gia a11y để viết spec tốt. Chỉ cần tự mình thử rút phích chuột ra và dùng feature bằng bàn phím trong 2 phút — bạn sẽ phát hiện 80% vấn đề lớn nhất.
Bài tập thực hành
Hãy chọn một feature có UI mà bạn (hoặc team bạn) đang làm, rồi thực hiện:
- Viết mục "Accessibility" cho feature đó, mở đầu bằng câu tuyên bố mức tuân thủ (WCAG 2.1 AA).
- Liệt kê 5 acceptance criteria a11y cụ thể cho feature, mỗi tiêu chí phải kiểm tra được. Bám theo POUR: ít nhất một tiêu chí cho keyboard, một cho screen reader label, một cho contrast/màu sắc, một cho focus state, và một cho thông báo lỗi.
- Làm "keyboard-only test": mở feature thật (hoặc prototype), rút chuột hoặc không động vào trackpad, thử hoàn tất luồng chính chỉ bằng Tab/Enter/mũi tên. Ghi lại mọi chỗ bạn bị "kẹt".
- Đối chiếu danh sách chỗ kẹt với 5 acceptance criteria bạn vừa viết — có lỗ hổng nào bạn đã bỏ sót không? Bổ sung tiêu chí.
- Thử thách nâng cao: lấy một thông báo lỗi bất kỳ trong feature, viết lại sao cho nó truyền tải trạng thái lỗi không chỉ bằng màu đỏ mà còn bằng icon + text rõ ràng.
Tóm tắt
- A11y phải là một mục cố định trong spec, không phải việc làm sau. Có ba lý do: pháp lý (ADA, EAA 2025), thương mại (~15% dân số có khuyết tật), và chất lượng code (semantic HTML).
- Dùng khung WCAG, nguyên tắc POUR (Perceivable, Operable, Understandable, Robust), nhắm mức AA làm ngôn ngữ chung cho cả team.
- Biến a11y thành acceptance criteria cụ thể, kiểm tra được: keyboard navigation, screen reader label, contrast ≥ 4.5:1, focus state, không-chỉ-dựa-vào-màu, touch target ≥ 44px.
- A11y rẻ khi làm sớm, đắt khi retrofit — như bài học từ ShopViet và PayMango.
- Mẹo nhanh nhất để tự kiểm tra: dùng feature chỉ bằng bàn phím trong 2 phút.