Mở đầu — vì sao bài này quan trọng
Ở Việt Nam, có một sự thật mà bất kỳ người làm design nào cũng phải khắc cốt ghi tâm: người dùng của bạn chủ yếu ở trên điện thoại. Theo báo cáo của các nền tảng đo lường như Statcounter, hơn 65–70% lượt truy cập web tại Việt Nam đến từ thiết bị di động, và với nhiều ứng dụng thương mại điện tử hay ngân hàng, con số này còn cao hơn nữa. Nếu bạn tối ưu accessibility (khả năng tiếp cận) chỉ cho desktop, bạn đang bỏ quên phần lớn khán giả thật sự của mình.
Nhưng đây là điểm mà rất nhiều học viên hiểu lầm: accessibility trên mobile KHÔNG chỉ là "phóng to giao diện desktop cho vừa màn hình nhỏ". Mobile có cả một hệ sinh thái riêng — cách người khiếm thị vuốt màn hình, cách người có tay run chạm vào nút, cách màn hình xoay ngang xoay dọc, cách hệ điều hành cung cấp trình đọc màn hình riêng. Có những vấn đề accessibility chỉ xuất hiện trên mobile mà bạn không bao giờ gặp trên desktop, và ngược lại.
Trong toàn bộ khóa học này, các bài trước đã dạy bạn nền tảng WCAG, semantic HTML, ARIA, keyboard navigation, screen reader cơ bản. Bài 36 này là nơi chúng ta gom tất cả kiến thức đó lại và soi qua lăng kính riêng của thiết bị di động: những đặc thù mà chỉ mobile mới có. Đây là kiến thức phân biệt một designer "biết accessibility về lý thuyết" với một designer thực sự làm sản phẩm cho thị trường Việt Nam.
Khái niệm cốt lõi
Hai tầng của mobile accessibility: Web mobile vs Native
Điều đầu tiên bạn cần phân biệt rõ: mobile accessibility có hai tầng khác nhau, và chúng dùng công nghệ khác nhau.
Web mobile là khi người dùng mở website của bạn bằng trình duyệt trên điện thoại — Safari trên iOS, Chrome trên Android. Ở tầng này, toàn bộ WCAG vẫn áp dụng giống như trên desktop: color contrast, alt text, heading structure, form labels... Tất cả những gì bạn đã học đều còn nguyên giá trị. Nhưng cộng thêm vào đó là một loạt yêu cầu đặc thù của mobile mà chúng ta sẽ đi sâu bên dưới.
Native app là ứng dụng cài trực tiếp trên điện thoại (viết bằng Swift/SwiftUI cho iOS, Kotlin/Jetpack Compose cho Android, hoặc cross-platform như Flutter, React Native). Ở tầng này, WCAG không áp dụng trực tiếp theo cùng cách — thay vào đó, mỗi nền tảng có hướng dẫn accessibility riêng của hãng: Apple có Human Interface Guidelines phần Accessibility, Google có Material Design Accessibility. Nhưng nguyên tắc POUR (Perceivable, Operable, Understandable, Robust) mà bạn đã học ở Bài 6 vẫn là kim chỉ nam chung.
Điểm mấu chốt: dù là web hay native, người dùng khuyết tật trên mobile đều dựa vào assistive technology tích hợp sẵn của hệ điều hành, không phải phần mềm bên thứ ba như trên desktop.
Screen reader trên mobile: VoiceOver và TalkBack
Trên desktop, screen reader phổ biến là NVDA hay JAWS (bạn đã học ở Bài 13). Nhưng trên mobile, câu chuyện hoàn toàn khác:
- VoiceOver — trình đọc màn hình tích hợp sẵn trong iOS/iPadOS. Người dùng vuốt sang phải để chuyển đến phần tử tiếp theo, chạm đôi (double-tap) để kích hoạt, và dùng "rotor" (xoay hai ngón tay) để chuyển chế độ điều hướng theo heading, link, form...
- TalkBack — trình đọc màn hình tích hợp sẵn trong Android. Cách tương tác tương tự: vuốt để duyệt, chạm đôi để kích hoạt.
Orientation — không được khóa xoay màn hình
WCAG 2.1 có một tiêu chí đặc thù cho mobile: 1.3.4 Orientation (Mức AA). Nội dung không được giới hạn chỉ hiển thị ở một hướng (dọc HOẶC ngang) trừ khi hướng đó là thiết yếu. Lý do rất nhân văn: nhiều người khuyết tật gắn điện thoại cố định vào xe lăn ở hướng ngang, hoặc người không thể xoay điện thoại bằng tay. Nếu app của bạn ép buộc chỉ chạy dọc, bạn đã loại trừ họ.
Reflow, zoom và text spacing trên màn hình nhỏ
Đây là nơi mobile giao thoa với các tiêu chí bạn sẽ học kỹ hơn ở Bài 31. Trên mobile, một lỗi kinh điển là developer đặt thẻ meta viewport với user-scalable=no hoặc maximum-scale=1.0 — điều này chặn người dùng pinch-to-zoom để phóng to chữ. Với người thị lực kém, đây là thảm họa. WCAG 1.4.4 (Resize Text) yêu cầu người dùng phóng to được đến 200% mà không mất nội dung.
Touch target và cử chỉ thay thế
Hai đặc thù mobile cực kỳ quan trọng, liên quan chặt đến Bài 28:
- Touch target size: WCAG 2.5.5 khuyến nghị vùng chạm tối thiểu 44×44 CSS pixel (Apple) hoặc 48×48 dp (Android Material). Trên desktop chuột chính xác đến từng pixel, nhưng ngón tay thì không — nút quá nhỏ khiến người có tay run, người lớn tuổi bấm nhầm liên tục.
- Cử chỉ thay thế (WCAG 2.5.1 Pointer Gestures): mọi thao tác cần cử chỉ phức tạp (vuốt hai ngón, kéo, xoay, path-based) phải có cách thay thế bằng một thao tác chạm đơn giản. Ví dụ: nếu người dùng phải vuốt để xóa item trong danh sách, bạn phải có thêm nút "Xóa" bấm được.
Tình huống thực tế
Ví dụ 1 — App ngân hàng ép khóa màn hình dọc
Một ngân hàng số tại Việt Nam (giả định tên là "VNBank Digital") ra mắt app mobile banking với thiết kế rất đẹp, nhưng lập trình viên khóa cứng app chỉ chạy ở chế độ portrait (dọc) "cho gọn". Sau khi ra mắt, bộ phận chăm sóc khách hàng nhận được phản ánh từ một khách hàng bị liệt hai tay, sử dụng điện thoại gắn cố định theo hướng ngang trên giá đỡ xe lăn. Với anh, app hoàn toàn không dùng được — màn hình luôn xoay sai chiều so với thiết bị của anh.
Diễn giải: Đây chính là vi phạm WCAG 1.3.4 Orientation. Đội ngũ không cố ý loại trừ ai, họ chỉ nghĩ "banking thì ai chả cầm dọc". Nhưng "đa số cầm dọc" không có nghĩa là "được phép chặn hướng ngang". Giải pháp cực kỳ đơn giản: bỏ khóa orientation, để layout responsive tự thích ứng cả hai hướng. Chi phí kỹ thuật nhỏ, nhưng mở ra cánh cửa cho cả một nhóm người dùng.
Bài học: Đừng bao giờ khóa orientation trừ khi thực sự thiết yếu (ví dụ app xem phim, game landscape). "Gọn gàng cho developer" không phải lý do chính đáng.
Ví dụ 2 — Sàn thương mại điện tử với nút "Thêm vào giỏ" quá nhỏ trên mobile
Một sàn TMĐT tương tự Tiki hay Shopee (giả định là "MuaNhanh") có trang chi tiết sản phẩm mà trên desktop nhìn rất ổn. Nhưng khi đội QA test trên mobile với VoiceOver bật, họ phát hiện nhiều vấn đề: nút "Thêm vào giỏ" chỉ cao 32px (nhỏ hơn ngưỡng 44px), các nút chọn size sản phẩm nằm sát nhau chỉ cách 4px, và quan trọng nhất — thao tác "vuốt để xem thêm ảnh sản phẩm" không có nút thay thế nào.
Kết quả đo lường: tỷ lệ bấm nhầm (mis-tap) trên mobile cao hơn desktop 3 lần ở khu vực chọn size, và một số người dùng VoiceOver không thể xem hết ảnh sản phẩm vì họ không thực hiện được cử chỉ vuốt carousel.
Diễn giải: Nhóm đã tăng touch target lên tối thiểu 44×44px, thêm khoảng cách (spacing) tối thiểu 8px giữa các nút chọn size, và thêm hai nút mũi tên trái/phải cho carousel ảnh (giải quyết WCAG 2.5.1). Sau cập nhật, tỷ lệ bấm nhầm giảm rõ rệt và tỷ lệ hoàn tất mua hàng trên mobile tăng lên — một minh chứng rằng accessibility tốt cũng là UX tốt cho tất cả mọi người, không riêng người khuyết tật.
Bài học: Touch target và cử chỉ thay thế là hai lỗi mobile phổ biến nhất và dễ khắc phục nhất. Chúng còn cải thiện conversion rate — một lập luận rất mạnh khi bạn thuyết phục quản lý đầu tư vào accessibility.
Ví dụ 3 — Trang tin tức chặn zoom bằng viewport
Một tòa soạn báo điện tử đặt thẻ meta viewport như sau để "layout không bị vỡ": <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">. Một độc giả lớn tuổi bị viễn thị phản ánh rằng bà không thể pinch-to-zoom để phóng to chữ trên điện thoại như các trang web khác. Với cỡ chữ mặc định 14px, bà phải nhờ con cháu đọc hộ.
Diễn giải: user-scalable=no và maximum-scale=1 là hai kẻ thù trực tiếp của accessibility mobile — chúng chặn cơ chế zoom mà người thị lực kém phụ thuộc vào. Đội kỹ thuật gỡ bỏ hai thuộc tính này, chỉ giữ width=device-width, initial-scale=1. Layout thực ra không hề vỡ, vì họ đã dùng responsive design đúng cách; nỗi lo "vỡ layout" chỉ là suy đoán chưa kiểm chứng.
Bài học: Không bao giờ chặn zoom. Nếu bạn thấy user-scalable=no trong codebase, hãy xóa ngay — đó gần như luôn là một lỗi accessibility.
Hướng dẫn từng bước
Đây là quy trình thực tế để kiểm tra và cải thiện mobile accessibility cho một sản phẩm:
Bước 1 — Xác định tầng của bạn. Sản phẩm là web mobile, native app, hay cả hai (hybrid)? Điều này quyết định bạn dùng bộ hướng dẫn nào: WCAG (web) hay HIG/Material (native). Nếu là web responsive, WCAG là chuẩn chính.
Bước 2 — Kiểm tra viewport và zoom. Mở source code, tìm thẻ meta viewport. Đảm bảo KHÔNG có user-scalable=no và KHÔNG có maximum-scale dưới 5. Test thực tế: mở trang trên điện thoại thật, thử pinch-to-zoom — phải phóng to được ít nhất 200%.
Bước 3 — Đo touch target. Dùng thước đo trong DevTools (chế độ device emulation) hoặc trực tiếp trên máy. Mọi phần tử tương tác (nút, link, checkbox, icon bấm được) phải đạt tối thiểu 44×44px (iOS) hoặc 48×48dp (Android). Chú ý khoảng cách giữa các target liền kề.
Bước 4 — Test orientation. Xoay điện thoại ngang và dọc. Nội dung phải hiển thị và dùng được ở cả hai hướng. Nếu bạn khóa orientation, tự hỏi: có thực sự thiết yếu không?
Bước 5 — Test bằng screen reader thật. Bật VoiceOver (iOS: Cài đặt > Trợ năng > VoiceOver) hoặc TalkBack (Android: Cài đặt > Trợ năng > TalkBack). Vuốt sang phải để duyệt qua toàn bộ trang. Kiểm tra: mọi phần tử có được đọc không? Thứ tự đọc có hợp lý không? Nút icon có nhãn (label) không hay chỉ đọc "button"?
Bước 6 — Kiểm tra cử chỉ thay thế. Với mỗi thao tác cần vuốt/kéo/pinch, xác nhận có cách thay thế bằng chạm đơn. Carousel cần nút mũi tên; swipe-to-delete cần nút xóa hiện rõ.
Bước 7 — Kiểm tra reflow. Đặt màn hình ở 320px CSS width (tương đương iPhone SE). Nội dung không được yêu cầu cuộn ngang (horizontal scroll) để đọc — trừ những thành phần đặc thù như bảng dữ liệu lớn.
Lỗi thường gặp & mẹo
Lỗi 1 — Chặn zoom bằng viewport. Như đã phân tích, user-scalable=no là lỗi số một. Mẹo: tìm kiếm chuỗi này trong toàn bộ codebase ngay hôm nay và xóa đi.
Lỗi 2 — Icon button không có nhãn. Trên mobile, rất nhiều nút chỉ là một icon (ví dụ icon giỏ hàng, icon menu ba gạch). Nếu không có aria-label (web) hoặc accessibilityLabel (native), VoiceOver chỉ đọc "button" — người khiếm thị không biết nút làm gì. Mẹo: mọi icon button phải có nhãn văn bản mô tả hành động, ví dụ aria-label="Mở giỏ hàng".
Lỗi 3 — Touch target dựa vào kích thước icon thay vì vùng chạm. Icon có thể nhỏ (24px) về mặt hình ảnh, nhưng vùng chạm phải lớn hơn (44px). Mẹo: dùng padding để mở rộng vùng chạm mà vẫn giữ icon nhỏ gọn về thị giác.
Lỗi 4 — Hover-only interaction trên mobile. Nhiều component (tooltip, dropdown) chỉ hiện khi hover. Nhưng mobile không có hover! Ngón tay hoặc chạm hoặc không. Mẹo: mọi thông tin ẩn sau hover phải hiện được bằng chạm/focus trên mobile.
Lỗi 5 — Quên test trên thiết bị thật. Emulator trong DevTools không mô phỏng chính xác VoiceOver/TalkBack. Mẹo: luôn test screen reader trên ít nhất một máy iOS và một máy Android thật. Ở Việt Nam, cả hai hệ điều hành đều phổ biến, đừng chỉ test một bên.
Lỗi 6 — Focus order khác thứ tự thị giác. Trên mobile, nếu bạn dùng CSS để đổi vị trí phần tử mà không đổi thứ tự DOM, người dùng VoiceOver sẽ nghe nội dung theo trật tự khác với những gì họ thấy. Mẹo: giữ thứ tự DOM khớp với thứ tự đọc logic.
Bài tập thực hành
Bài tập 1 — Audit viewport và zoom. Chọn 3 website Việt Nam bạn hay dùng (ví dụ một báo điện tử, một sàn TMĐT, một app ngân hàng dạng web). Mở trên điện thoại, thử pinch-to-zoom. Ghi lại: trang nào chặn zoom? Kiểm tra source (View Source trên mobile hoặc DevTools) xem có user-scalable=no không.
Bài tập 2 — Đo touch target. Chọn một trang chi tiết sản phẩm bất kỳ trên mobile. Dùng DevTools device mode, đo kích thước các nút chính (thêm vào giỏ, mua ngay, chọn size). Liệt kê những nút nhỏ hơn 44×44px và đề xuất cách sửa.
Bài tập 3 — Trải nghiệm screen reader. Bật VoiceOver (iOS) hoặc TalkBack (Android) trên chính điện thoại của bạn. Nhắm mắt và thử hoàn thành một tác vụ đơn giản: tìm và "thêm một sản phẩm vào giỏ hàng" chỉ bằng cách nghe. Ghi lại những chỗ bạn bị mắc kẹt — đó chính là những rào cản mà người khiếm thị gặp hằng ngày.
Bài tập 4 — Săn cử chỉ không có thay thế. Tìm một component dùng cử chỉ vuốt (carousel ảnh, swipe-to-delete, kéo để làm mới). Kiểm tra xem có cách thay thế bằng chạm đơn không. Nếu không, viết đề xuất bổ sung.
Tóm tắt
Mobile accessibility không phải là phiên bản thu nhỏ của desktop accessibility — nó là một lĩnh vực có đặc thù riêng mà mọi designer làm cho thị trường Việt Nam (nơi mobile chiếm đa số) phải nắm vững. Những điểm cốt lõi cần nhớ:
- Có hai tầng: web mobile (WCAG áp dụng đầy đủ, cộng đặc thù mobile) và native app (theo HIG của Apple / Material của Google, nhưng nguyên tắc POUR vẫn là chung).
- Screen reader trên mobile là VoiceOver (iOS) và TalkBack (Android), điều hướng bằng cử chỉ chứ không phải phím tắt. Icon button luôn cần nhãn.
- Không bao giờ chặn zoom bằng
user-scalable=no— đây là lỗi phổ biến và nghiêm trọng nhất. - Touch target tối thiểu 44×44px (iOS) hoặc 48×48dp (Android), với khoảng cách đủ giữa các nút.
- Không khóa orientation trừ khi thực sự thiết yếu (WCAG 1.3.4).
- Mọi cử chỉ phức tạp phải có thao tác chạm đơn thay thế (WCAG 2.5.1).
- Test trên thiết bị thật, cả iOS lẫn Android — emulator không đủ.