Chỉ là những tính năng web bình thường
(heather-buchel.com)- Khi số lượng nền tảng mạng xã hội mới, client, ứng dụng và các bản port web dựa trên React Native tăng lên, ngày càng có nhiều trường hợp website đánh mất hành vi web cơ bản mà người dùng mong đợi
- Các nguyên nhân chính được nhắc đến gồm áp lực ra mắt nhanh, thiếu kỹ sư UI, thiết kế ưu tiên cảm ứng trên di động, và các cách triển khai dùng JavaScript để thay thế hành vi mặc định của trình duyệt
- Các tính năng mặc định của trình duyệt như sao chép văn bản, nhấp chuột phải vào liên kết và
ctrl + click, phóng to trình duyệt, bố cục responsive,:hovervà:focus, cập nhật URL·lịch sử, thanh cuộn,ctrl + fcần phải tiếp tục hoạt động như bình thường - Ở các thẻ có thể nhấp, việc bỏ
pointer-eventshoặc chồng nhiều lớp lên nhau, hay triển khai điều hướng bằngdivvàon-clickthay vì anchor, đều phá vỡ trải nghiệm liên kết thông thường - Dù có nhiều điểm chồng lấp với vi phạm accessibility, web app vẫn nên duy trì những tính năng web bình thường mà người dùng mong đợi, thay vì cố trông giống ứng dụng di động
Những hành vi cơ bản mà website đã đánh mất
- Ngày càng có nhiều dự án web chặn mất những tính năng web bình thường mà người dùng mong đợi
- Khi các nền tảng mạng xã hội mới tăng lên, nhiều client và ứng dụng cũng được tạo ra, và cũng có không ít trường hợp cố gắng chia sẻ mã giữa các nền tảng như React Native
- Bản thân những nỗ lực đó là tích cực, nhưng không chỉ các yêu cầu accessibility cơ bản như văn bản
altcho ảnh bị bỏ sót, mà cả cách tương tác thông thường của web cũng bị mất theo - Có thể thấy các nguyên nhân sau
- Áp lực phải phát hành thật nhanh đến mức có thể kiểm thử được
- Dự án không có kỹ sư UI
- Thiết kế ưu tiên nhập liệu bằng cảm ứng trên di động và bỏ qua các phương thức nhập hay thiết bị khác
- Cách triển khai lách qua hoặc thay thế hành vi mặc định của trình duyệt bằng JavaScript
Những tính năng web bình thường cần được giữ lại
- Sao chép văn bản phải hoạt động được
- Trong các component thẻ có thể nhấp, nếu bỏ
pointer-eventshoặc chồng lớp vùng có thể nhấp, việc chọn và sao chép văn bản có thể bị chặn
- Trong các component thẻ có thể nhấp, nếu bỏ
- Các phần tử điều hướng như liên kết phải giữ nguyên chức năng liên kết
- Cần có thể mở menu ngữ cảnh bằng nhấp chuột phải để sao chép văn bản hoặc địa chỉ liên kết
- Các phím tắt liên kết thông thường như
ctrl + clicktrên Windows để mở trong tab mới phải hoạt động - Nên dùng phần tử anchor thay vì gắn
on-clickvàodivđể điều hướng
- Khi phóng to trình duyệt, bố cục không được vỡ, và người dùng phải có thể phóng to để đọc
- Web responsive không nên vừa dưới 1200px là rơi ngay về một bố cục di động đơn giản; ngay cả ở viewport hẹp cũng cần tận dụng không gian hợp lý
- Mastodon và Twitter có thể xem là ví dụ về việc khi thu hẹp chiều rộng trình duyệt, UI vẫn giữ được cảm giác quen thuộc và nhìn chung tận dụng không gian khá tốt
- Web app cần cung cấp đúng các trạng thái tương tác như
:hover,:focus,:active- Ở một số trường hợp port ứng dụng React Native sang web, có khi không có style
:hoverhoặc:focus, hoặc xuất hiện style:activetrông kỳ lạ như bị vô hiệu hóa
- Ở một số trường hợp port ứng dụng React Native sang web, có khi không có style
- Nếu sau khi nhấp mà UI thay đổi hoàn toàn như sang một trang mới, thì lịch sử trình duyệt và URL cũng phải thay đổi theo
- Nếu không thể liên kết đến một trạng thái UI trông như một trang độc lập, và trạng thái biến mất sau khi điều hướng, khả năng sử dụng sẽ giảm
- Không nên ẩn thanh cuộn
- Người dùng có thể muốn nhấp và kéo thanh cuộn
- Không nên chặn các phím tắt trình duyệt thông thường để thay bằng chức năng nội bộ của ứng dụng
- Nếu làm cho
ctrl + fmở ô tìm kiếm tùy biến trong app, chức năng tìm kiếm trên trang có thể không hoạt động như bình thường
- Nếu làm cho
- Dù có nhiều phần trùng với các mục có thể bị xem là vi phạm accessibility, trọng tâm ở đây là làm sao để web app không phá vỡ kỳ vọng cơ bản về trình duyệt của người dùng
- Có thể tiếp tục bàn về các ví dụ bị thiếu trên Mastodon
3 bình luận
Có vẻ nội dung bài viết bị nhầm.
Ồ, thú vị thật. Có vẻ như việc crawl chính bài viết trên blog đó đang diễn ra hơi bất thường. Có lẽ phải xem lại phần crawler một lần.
Ý kiến trên Hacker News
Nếu học web bằng React trước rồi mới học HTML sau, sẽ có chuyện bạn không còn để ý đến hành vi mặc định của liên kết
Khi tôi gia nhập nhóm, mọi liên kết đều là nút bấm, phần tử tùy ý hoặc được xử lý bằng
onClick; không ai phàn nàn, nhưngCtrl+clicktrở nên vô dụng và menu chuột phải cũng không đưa ra các tùy chọn như mong đợiRiêng về liên kết thì tôi nghĩ không có gì để thương lượng
Ngay cả archbee, một nền tảng tài liệu được YC đầu tư, cũng không thể mở kết quả tìm kiếm trong tab mới, nên bạn phải mở một kết quả trong tab hiện tại, nếu không đúng thì quay lại, tìm kiếm lại rồi mở kết quả tiếp theo
Có thể xem ví dụ ở đây: https://docs.sparklayer.io/
Thật kỳ lạ và phát điên khi một dịch vụ Internet lớn như vậy lại có vấn đề truy cập rõ ràng đến thế
Cũng có lý do là không cần tài khoản, nhưng bạn có thể nhấp chuột phải vào chuỗi tweet để mở trong tab mới
Với đặc thù hội thoại trên Twitter, tôi muốn mở nhiều chuỗi mới để xem trong khi vẫn giữ nguyên vị trí trên trang gốc, nhưng UI Twitter thật sự khiến việc này rất khó
Không có nhiều thứ gây khó chịu hơn chuyện này; nếu phải chọn thì chắc chỉ có việc làm hỏng lịch sử duyệt web của trình duyệt
Nếu nút quay lại hoạt động tức thì và mượt mà thì còn có thể tha thứ, nhưng thực tế là bạn phải chờ nội dung tải lại và còn mất cả vị trí cuộn
Tệ hơn nữa là có những trang như Facebook ép trạng thái popup chat giống nhau trên nhiều tab. Đóng ở một tab thì tab khác cũng đóng theo, trong khi việc mở nhiều tab là có lý do riêng
Ngay khoảnh khắc bạn can thiệp vào hành vi có sẵn, tôi cho rằng bạn cũng gánh luôn trách nhiệm đối với nó
“Tính năng” bạn tạo ra không chỉ nằm trong phạm vi hẹp mà người thiết kế dự định, mà trở thành toàn bộ trải nghiệm thực tế của khách truy cập
Nếu thay đổi logic của nút quay lại, tức là bạn đang thay đổi chính ý nghĩa mà thao tác quay lại mang lại trên trang đó, và bạn cũng phải chịu trách nhiệm khi kết quả là người dùng bối rối, tức giận chửi đó là “trang bị hỏng”
Cần nghĩ xem bạn có thật sự sẵn sàng chịu trách nhiệm cả với những hành vi khác nhau giữa từng trình duyệt và hệ điều hành, như thanh cuộn, hay không
Rốt cuộc, điều đó chẳng khác nào khiến website nói một thứ ngôn ngữ creole, nên cũng không có gì lạ nếu khách truy cập không hiểu ngôn ngữ đó hoặc “diễn giải sai”
Những tính năng kiểu này không chỉ nên tránh vì muốn tử tế với khách truy cập; lợi ích thu được có vẻ hữu hạn, còn thiệt hại thì gần như vô hạn
Những trang phớt lờ các thành ngữ này trở nên khó dùng hơn vì chúng không nói thứ ngôn ngữ mà người dùng đã quen
Cũng có một bài viết dài về sự mất mát của các thành ngữ thiết kế: https://loeber.substack.com/p/4-bring-back-idiomatic-design
Tôi xem đây là việc biến website thành ứng dụng, và đã đến lúc phải dừng lại
Website nên quay lại với server-side rendering và chỉ thêm JavaScript ở mức cần thiết
Ngược lại, web app có thể xử lý UX nhiều hơn một chút nếu điều đó có giá trị với người dùng, nhưng chừng nào còn nằm trong trình duyệt thì các nguyên tắc cơ bản vẫn được áp dụng
Tôi ủng hộ web app vì đó là nền tảng phát triển mà ai cũng có thể tiếp cận bên ngoài hàng rào của các app store, nhưng cần ngừng đối xử với mọi website như ứng dụng
Nếu một trang muốn xuất hiện trong kết quả công cụ tìm kiếm, thì đó là website chứ không phải web app
Accept: text/markdowncho tài liệu thô, nhưng tôi nghĩ từ khoảnh khắc CSS xuất hiện thì con tàu đó đã rời bến rồiMay là nhờ những thứ như React Server Components, có vẻ chúng ta đang quay lại hướng thêm JavaScript từng chút một vào website, nên tôi thấy mừng
Đây là vấn đề có thể giải quyết nếu dành đủ thời gian
Tôi không hiểu vì sao các website ngân hàng lại chặn dán
Đến lúc nhận ra là không thể dán thì mình đã sao chép văn bản xong rồi
Nhập tay thì dễ sai hơn, còn nếu clipboard đã bị nhiễm bẩn thì khi nhận ra lệnh dán bị cấm, việc sao chép cũng đã hoàn tất rồi
Dường như người ta tưởng tượng đó là một biện pháp bảo mật và tự nguyện sao chép theo
Ngay từ đầu tôi đã không hiểu lý do chặn người dùng dán là gì
“Mật khẩu” đó chỉ là 6 chữ số, và tôi còn không được tự đặt. Như thể 6 chữ số an toàn hơn hẳn chuỗi ngẫu nhiên 16 ký tự do trình quản lý mật khẩu tạo ra
Trang bắt nhập bằng các nút ở vị trí ngẫu nhiên trong trang, nhưng nếu thiết bị đã bị nhiễm đến mức phím gõ và cú nhấp bị ghi lại, thì có lẽ kẻ tấn công cũng có thể đọc thẳng mật khẩu từ bộ nhớ trình duyệt
Xét từ góc độ bảo mật, đó là một quyết định tệ đến khó tin
Họ thử đủ cách để gây khó cho bot, rồi một ngày nọ các lập trình viên bị quản lý cấp trung thúc ép chặn sao chép–dán trên trang đăng nhập, và bot tạm dừng lại
Vài ngày sau bot vượt qua, nhưng “bản sửa” trước đó vẫn được giữ lại với suy nghĩ “có thể chặn được một số bot”
Thế là khoảng hơn 10 dòng JavaScript đó sống sót đến tận bản rewrite v6, rồi sau khi làm lại từ đầu vài tháng hoặc vài năm, lệnh cấm tương tự lại được đưa vào
Tuyệt đối không phải nói từ kinh nghiệm đâu
https://techcrunch.com/2018/07/03/new-malware-highjacks-your...
Có thể họ đã nghĩ đến loại đó
Tôi bực khi các lập trình viên JS hào nhoáng giấu sự phức tạp và tính năng không ai yêu cầu phía sau menu select trông như HTML native
Tôi hay gặp ở phần nhập thành phố và bang: thành phố là ô nhập văn bản, còn bang là menu thả xuống/select
Vì là người Texas, tôi thường nhập thành phố, nhấn Tab tới menu chọn bang rồi nhấn
t,tđể chuyển sang phần tử form tiếp theoNhưng dạo này đó lại là ô tìm kiếm văn bản được trang trí như dropdown, nên
t,tkhông chọn Tennessee rồi đến Texas mà trở thành tìm kiếm đúng chuỗittNó chỉ hoạt động đúng như kỳ vọng với người dùng chuột bấm vào hình tam giác rồi cuộn danh sách bang
Nếu chưa hỏng thì đừng sửa
Trong lịch sử,
<select>thật rất khó hoặc không thể thay đổi style hay mở rộng hành vi, nên nhiều ứng dụng tự triển khai lại và thường làm rất tệCó vẻ các lựa chọn thay thế tích hợp sẵn có thể style được đang xuất hiện
Ngoài ra, vì việc chia sẻ mã giữa ứng dụng, framework và công ty rất khó, nên chỉ các công ty lớn mới có thể tạo ra những thành phần thay thế tích hợp sẵn đầy đủ tính năng, khả năng truy cập và khả năng tùy biến
Web Components có thể giải quyết vấn đề này bằng cách cho phép cộng tác toàn cầu trên các thành phần đầu cuối phổ biến như
<select>Bài liên quan: https://blogs.windows.com/msedgedev/2022/05/05/styling-selec...
Tôi cho rằng khá nhiều hành vi liên kết bị hỏng là do thiếu phương thức cấp cao để ghi đè hành vi liên kết mặc định
Ví dụ, nếu muốn mở liên kết trong modal, tôi không muốn gắn listener sự kiện click. Sự kiện click quá thấp cấp, khiến tôi phải tự kiểm tra các phím bổ trợ
Điều tôi thật sự muốn là nói với trình duyệt: “nếu URL cửa sổ hiện tại sắp thay đổi vì phần tử anchor này, hãy gọi hàm này thay vào đó”
Khi đó người dùng vẫn có thể tự do mở liên kết trong cửa sổ mới hoặc tab mới, và trong trường hợp đó mã của tôi sẽ không chạy
CSS cũng tương tự: tôi không muốn chỉ định ảnh con trỏ cho mọi phần tử và pseudo-class. Tôi muốn nói “ở những nơi định dùng con trỏ tay/chờ/thay đổi kích thước mặc định, hãy dùng ảnh tùy chỉnh này”
Như vậy, kể cả khi có phần tử hoặc UI mới, mã vẫn an toàn cho tương lai
Có vẻ đôi khi một số API trình duyệt cũng mắc vấn đề XY
Chỉ cần đăng ký
onclicktrên thẻ và hủy hành vi điều hướng mặc định trong event handlerNếu người dùng tắt JavaScript thì site vẫn hoạt động tốt, còn các hành vi trình duyệt tích hợp như menu liên kết khi nhấp phải hay
Ctrl+clickvẫn hoạt động nguyên vẹnTuy nhiên đó là một “mẹo” khá obscure, nên sẽ tốt hơn nếu DOM API làm việc này dễ hơn
Tôi nghĩ đây là use case của Navigation API
Thứ cần có không phải sự kiện click hay pointer, mà là một sự kiện visit cấp cao hơn
Khi lần đầu xem Flutter Gallery, tôi ngạc nhiên vì cảm giác như mọi thứ trong trình duyệt web đều bị hỏng: https://gallery.flutter.dev
Tôi nhớ đặc biệt là ví dụ Reply
Ctrl+clickhay nút chuột giữa trên liên kết không hoạt động, nhấp phải cũng không, chọn và sao chép văn bản cũng không, do cấu trúc kỹ thuật nên không thể inspect element, và thử phóng to trang cũng chẳng có gì xảy raNhớ lại trải nghiệm đó cùng với một số triển khai SPA làm bằng công nghệ truyền thống hơn, tôi thấy bài viết này nói có lý
Dù là web hay mobile, chưa demo Flutter nào thuyết phục được tôi rằng nó có UX dùng được
Nếu lời hứa của Flutter là giống nhau ở mọi nơi, thì demo này hẳn cũng tệ như vậy trên desktop
Cũng mong đừng ghi đè hành vi cuộn
Đừng cố “cải thiện” để làm thao tác cuộn “mượt hơn”
Trên Windows có thể trông ổn, nhưng trên Mac, khi dùng thiết bị nhập của Apple, chuyển động của ngón tay trên trackpad hoặc chuột tương ứng 1:1 với chuyển động của đối tượng đang cuộn
Những kiểu “cải tiến” như vậy thường tạo cảm giác như đang cuộn trong mật đường
Nói chung, đừng cố cải thiện hành vi mặc định của trình duyệt
Một trong những điều tôi ghét ở web hiện đại lộn xộn là việc đụng vào History API
Khi nhấn một liên kết có vẻ thú vị từ nơi như HN, vào trang rồi cuộn, mọi tiêu đề hoặc thậm chí các phần tử chẳng mấy quan trọng cũng thêm mục vào lịch sử truy cập
Muốn quay lại trang gốc thì phải bấm nút quay lại đến cả triệu lần
Tôi ghét tất cả những ai làm chuyện này
Chỉ cần dùng phân trang là được
Có thể liên kết, tìm kiếm, điều hướng, và hoạt động đúng với lịch sử truy cập
Cuộn vô hạn phá hỏng tất cả những điều đó mà chẳng có lý do gì đáng kể
Thực ra ở đây có hai vấn đề lâu đời như chính web: kỳ vọng thấp và sự thiếu vắng các tiêu chuẩn/chuẩn mực để định nghĩa con người hoặc thực hành nghề nghiệp
Nhìn các tin tuyển dụng ngày nay thì toàn là “Senior Fullstack Engineer”, nhưng đọc vào thì thứ họ thật sự muốn thường là một tổ hợp Java hoặc Python, R, Spring, SQL
Nếu không phải fullstack mà vẫn viết như vậy thì chỉ làm lãng phí thời gian của mọi người, đồng thời gửi tín hiệu ra công chúng rằng họ không hiểu hoặc không quan tâm đến công nghệ
Trong lập trình, điều này được gọi là “vấn đề X/Y”. Đây là một anti-pattern: đáng ra phải giải quyết trạng thái đích X mong muốn, nhưng thay vào đó lại chỉ nói về cách tiếp cận Y mà mình muốn dùng
Vì vậy nhà tuyển dụng nhận 500 hồ sơ cho một tin đăng mà vẫn cảm thấy không có ai phù hợp
Điểm khởi đầu phải là mục tiêu: nên viết kiểu “Chúng tôi tuyển người để xây dựng ứng dụng client/server như thế này, ứng viên phải viết và hỗ trợ các tính năng X, Y, Z, còn các ràng buộc là A, B, C”
Lý do các công ty không làm được như vậy thường là vì họ không biết mình thực sự đang làm gì, và đã ôm một đống công nghệ hỏng sau khi đi qua nhiều con đường sai lầm. Vì thế mới gọi là nợ kỹ thuật
Khi mục tiêu rõ ràng như vậy, trong phỏng vấn cả công ty lẫn ứng viên đều biết cần kiểm tra điều gì và có thể sàng lọc nhau phù hợp. Nếu không, nó trở thành một quy trình kinh khủng như pha trộn giữa hẹn hò giấu mặt và gameshow
Ví dụ, có thể nêu rõ rằng công ty tuyển người để xây dựng một ứng dụng hội nghị truyền thông phân tán cao, nhà phát triển sẽ viết TypeScript, nối luồng dữ liệu từ socket qua pipe, làm việc ở cả trình duyệt lẫn máy chủ và viết tự động hóa kiểm thử
Các ràng buộc vận hành bao gồm tuân thủ WCAG AA, checklist tuân thủ quyền riêng tư do đội pháp lý lập, các cân nhắc hiệu năng nhắm đến tốc độ thực thi và độ trễ mạng; ứng viên lý tưởng phải thể hiện được trong phỏng vấn các giải pháp cho độ trễ mạng, logic ứng dụng trình duyệt và quản lý trạng thái dữ liệu streaming