Trung  Nguyen

Trung Nguyen

1657899960

Xây Dựng Bảng Thuật Ngữ Có Thể Truy Cập được Bằng JavaScript Vani

Đây là lần đầu tiên tôi viết một bài báo như thế này. Hầu hết các bài viết của tôi đều bắt nguồn từ một ý tưởng mà tôi có và sau đó tôi thực hiện nghiên cứu để làm cho nó hoạt động, nhưng bài viết này được lấy cảm hứng từ một dự án gần đây mà tôi đã thực hiện với nền tảng học tập điện tử Kognity , người đã quan tâm đến việc cung cấp cho người dùng của họ trải nghiệm trợ năng hàng đầu khi sử dụng nền tảng của họ.

Trong số nhiều phần của nền tảng mà chúng tôi có thể truy cập được là bảng chú giải thuật ngữ tương tác từ sách giáo khoa của họ có sẵn dưới dạng thanh bên có thể mở rộng / thu gọn trên nền tảng trực tuyến của họ. Vì chúng tôi đã có một kinh nghiệm thực sự tốt trong việc xây dựng một giải pháp thành công, dễ tiếp cận, nên tôi muốn chia sẻ nó.

Giải pháp Kognity được viết bằng Vue.js, nhưng phần lớn chức năng của nó là dành riêng cho nền tảng của họ - và bởi vì tôi muốn làm cho mọi thứ càng chung chung càng tốt cho bài đăng này - tôi sẽ triển khai một giải pháp tương tự trong vanilla JavaScript. Sẽ dễ dàng làm lại việc triển khai này cho nhiều khung công tác khác.

Lưu ý về ảnh chụp màn hình của bài viết này và cách sử dụng trình đọc màn hình

Có thể có sự khác biệt đáng kể giữa trình đọc màn hình và kết hợp trình duyệt và nhiều ảnh chụp màn hình trong bài viết này sẽ hiển thị cách hoạt động của trình đọc màn hình. Tôi chủ yếu sử dụng máy Mac và do đó hầu hết các ảnh chụp màn hình của tôi sẽ sử dụng VoiceOver trên Firefox, Chrome và Safari. Tuy nhiên, mã được trình bày trong bài viết này đã được thử nghiệm với NVDA và Firefox trên Windows. Trong những trường hợp có sự khác biệt về hành vi, sự khác biệt đó được ghi nhận.

Do những khác biệt đáng kể này, bạn có thể muốn xem xét sử dụng một giải pháp như Assistiv Labs để thử nghiệm vì họ có thể cung cấp cho máy ảo các thiết lập trình đọc màn hình khác nhau mà bạn có thể truy cập từ xa. Trong bất kỳ trường hợp nào, sẽ là sai lầm nếu chỉ kiểm tra mã này trên một tổ hợp trình đọc màn hình / trình duyệt vì sự khác biệt lớn trong đầu ra và khả năng của chúng, và bạn có thể dễ dàng bỏ lỡ các vấn đề.

Khám phá các ví dụ về bảng chú giải thuật ngữ

Bảng chú giải thuật ngữ Kognity

Vì vậy, trước tiên, chúng ta hãy xem cách hoạt động của bảng thuật ngữ Kognity. Trong ảnh chụp màn hình sau, bạn có thể thấy một phần của sách giáo khoa sinh học Kognity và nút để mở bảng chú giải thuật ngữ ở góc trên bên phải.

Bảng chú giải thuật ngữ Kognity

Khi bạn nhấp vào nút bảng thuật ngữ, bảng thuật ngữ sẽ mở ra và bạn thấy một cái gì đó giống như sau:

Bảng thuật ngữ Kognity khi mở

 

Bạn sẽ thấy một số chữ cái trong bảng chú giải bị chuyển sang màu xám - đây là những chữ cái không có bất kỳ mục nào liên quan đến phần cụ thể này của sách giáo khoa. Như bạn có thể thấy, chữ A có một vòng tròn màu xanh mòng két xung quanh nó để chỉ ra rằng đó là chữ cái được chọn khi bảng chú giải lần đầu tiên mở ra (tất nhiên, giả sử rằng có các mục dưới chữ A).

Có một số chức năng bổ sung được liên kết với bảng thuật ngữ này, chẳng hạn như lọc theo kiểu nhập văn bản; Tôi sẽ không triển khai chức năng tương tự trong bài viết này, nhưng sẽ đề cập đến nó cho đầy đủ.

Bảng chú giải thuật ngữ tiêu đề phim HBOMax

Tôi chắc rằng bạn đã từng thấy điều gì đó như thế này trước đây: các chữ cái trong bảng chữ cái được liệt kê ra và việc nhấp vào một trong các chữ cái sẽ hiển thị cho bạn một số nội dung liên quan đến chữ cái đó. Trong trường hợp này, đó là một bảng thuật ngữ, nhưng bạn thấy một mẫu giao diện người dùng tương tự để điều hướng các dịch vụ video, ví dụ ở đây trên HBOMax:

Màn hình tiêu đề HBOMax

Nếu bạn nhấp vào một trong các chữ cái ở thanh bên bên phải, trang sẽ cuộn xuống bộ phim đầu tiên có tiêu đề bắt đầu bằng chữ cái đó.

Vì vậy, tôi đoán chúng ta có thể đồng ý rằng đó là một thiết kế phổ biến, nhưng điều ít phổ biến hơn là một thiết kế dễ hiểu và dễ tiếp cận. Chúng tôi sẽ chứng minh điều này nhiều hơn một chút với ví dụ HBOMax này trong phần tiếp theo.

Tạo bảng thuật ngữ có thể truy cập được: Cách tiếp cận

Về bản chất, khả năng tiếp cận là một vấn đề về trải nghiệm người dùng, và mọi nhà phát triển và nhà thiết kế phải sử dụng trí tưởng tượng của họ để vật lộn với nó, giống như họ phải làm với bất kỳ việc sử dụng ứng dụng nào của họ. Bất kể bạn có thể có bộ khả năng cụ thể nào, bộ đó sẽ không phù hợp với tất cả người dùng của bạn.

Hành động tưởng tượng này về cơ bản là chìa khóa để tạo ra một ứng dụng có thể truy cập hợp lý, nhưng hãy lưu ý. Tôi nói có thể truy cập hợp lý để nhấn mạnh rằng, mặc dù có những phần sẽ rất khó, nỗ lực lập trình cần thiết để làm cho ứng dụng có thể truy cập được là rất nhỏ, miễn là bạn đã thực hiện công việc cần thiết là hình dung cách ứng dụng sẽ được sử dụng trong trường hợp khả năng của ai đó có lẽ khác xa với khả năng của bạn. Và thông thường, công việc cần thiết của trí tưởng tượng cũng không đặc biệt tiêu hao!

Xây dựng hồ sơ người dùng của chúng tôi

Đầu tiên, hãy hình dung cách người dùng với các nhóm khả năng cụ thể, khác nhau sẽ sử dụng nội dung và công cụ để tương tác với nội dung trên trang web của bạn. Có một bộ hồ sơ người dùng có thể hữu ích. Để xây dựng bảng thuật ngữ của chúng tôi, chúng ta sẽ hình dung ba cấu hình riêng biệt, như sau:

Hồ sơ người dùng 1: Người dùng không sử dụng bất kỳ thiết bị và kỹ thuật hỗ trợ nào

Điều này bao gồm những người không sử dụng thiết bị hoặc kỹ thuật hỗ trợ, nhưng vẫn có thể cần chúng hoặc thiếu một số công suất mà không dễ sửa chữa bằng các thiết bị sửa chữa. Vì vậy, ngoài người hoàn toàn không gặp bất kỳ vấn đề gì, trong danh mục này, chúng tôi sẽ đặt:

Chúng tôi có thể coi đây là người dùng bình thường cơ bản của chúng tôi.

Hồ sơ người dùng 2: Những người khuyết tật vận động

Điều này bao gồm những người chỉ sử dụng bàn phím và phím tắt tab để điều hướng một trang web, tức là những người không có khả năng sử dụng chuột hoặc bàn di chuột.

Hồ sơ người dùng 3: Những người sử dụng trình đọc màn hình

Có một số người có thể phù hợp với mô tả này. Có những người có thể nhìn thấy trang đủ tốt để tương tác mà không cần trình đọc màn hình, chẳng hạn như những người mắc chứng khó đọc hoặc khó xử lý ngôn ngữ khác, nhưng lại thích sử dụng trình đọc màn hình để được trợ giúp. Sau đó, có những người gặp khó khăn về thị giác không chính thức bị mù vẫn có thể thích sử dụng trình đọc màn hình để giúp họ. Cuối cùng, có những người dùng bị mù và hoàn toàn cần một trình đọc màn hình.

Bạn có thể đọc bảng phân tích thống kê sử dụng trình đọc màn hình từ Khảo sát người dùng trình đọc màn hình WebAim lần thứ chín , được cập nhật lần cuối vào ngày 30 tháng 6 năm 2021.

Làm thế nào để những người dùng khác nhau này sử dụng cùng một trang web?

Các nhà phát triển chưa quen với việc kiểm tra các vấn đề về khả năng tiếp cận quyết định kiểm tra cách mọi thứ hoạt động bằng cách lướt qua nó. Nếu bạn có thể nhấp vào các thứ, tương tác với chúng và đảm bảo chúng hoạt động chính xác, thì giả định rằng trang web có thể truy cập được.

Chắc chắn là một yêu cầu đối với khả năng truy cập là tất cả các yếu tố tương tác phải đạt được bằng phím tab, nhưng đó là yêu cầu chủ yếu đối với người dùng của chúng tôi trong nhóm hai, vì việc sử dụng phím tab sẽ phù hợp với những người có vấn đề về di động cũng có thể xử lý trực quan nội dung của trang.

Tuy nhiên, người dùng trình đọc màn hình yêu cầu các cách khác để sắp xếp và xử lý nội dung của trang và chúng tôi nên xem xét điều này trong giải pháp của mình.

Thiết kế rô-to web để sử dụng trình đọc màn hình

Cụ thể, mọi trình đọc màn hình đều có một cách để đọc các phần hữu ích của trang riêng biệt với thứ tự trang bình thường. Điều này hữu ích để tìm những gì bạn muốn làm trên một trang web và điều hướng đến các phần của trang mà bạn quan tâm.

Ví dụ, trong VoiceOver, đây được gọi là rô-to web (hoặc chỉ rô-to). Dưới đây là hình ảnh của rôto trên Kognity với bảng chú giải thuật ngữ đã đóng.

Rotor web Điều khiển biểu mẫu từ VoiceOver trên trang Kognity

Điều đầu tiên bạn sẽ nhận thấy là chỉ có 13 điều khiển biểu mẫu với nút thuật ngữ đóng. Thật tuyệt! Hãy tưởng tượng nếu bạn đang tương tác với cái này khi nó đang mở: sẽ có 12 nút, cộng với 26 nút cho bảng chữ cái tiếng Anh, tổng cộng có 38 mục để đọc. Đó là rất nhiều! Và, trong trường hợp của những người trong nhóm người dùng 3 có một chút thị giác, tất nhiên họ sẽ có thể sử dụng chế độ xem của phần tử trình đọc màn hình một cách trực quan.

Tại sao chúng tôi tạo một bảng thuật ngữ có thể truy cập được?

Để đảm bảo rằng mọi người có thể sử dụng tối ưu bảng thuật ngữ trên trang của chúng tôi, chúng tôi nên thiết kế một quy trình làm việc hợp lý. Nếu quy trình tương tác với trang không được suy nghĩ kỹ lưỡng, trang của chúng tôi sẽ không thể sử dụng được.

Để làm ví dụ về việc triển khai có vấn đề về khả năng tiếp cận, tôi sẽ chọn một chút về HBOMax. Tôi không có bất cứ điều gì chống lại họ (mặc dù tôi đã hy vọng có nhiều nội dung Warner Brothers cổ điển hơn), nhưng tôi vừa có tư cách thành viên và tôi nhận thấy những điều này bởi vì tôi là một nhà phát triển.

Giả sử chúng ta đang ở một trong các trang có điều hướng kiểu bảng thuật ngữ, chẳng hạn như Phim hài A – Z. Nếu chúng tôi đang sử dụng VoiceOver và quyết định kiểm tra rôto, rôto sẽ có sẵn khoảng 38 nút để sử dụng:

Điều khiển biểu mẫu từ VoiceOver trong ứng dụng HBOMax

Chỉ tám trong số các nút này có nhãn có ý nghĩa hoặc một nhãn cho chúng ta cơ hội hiểu chúng làm gì. Phần còn lại của chúng được gắn nhãn nút làm mờ .

“Nút mờ” là cách VoiceOver thông báo rằng một nút hiện đang bị vô hiệu hóa và ứng dụng không thể sử dụng được. Bạn có thể nghĩ rằng các nút bị mờ là để điều hướng các danh mục theo chữ cái đầu tiên của tiêu đề phim, nhưng khi bạn nhấp vào để xem các tiêu đề bắt đầu bằng chữ cái cụ thể đó, bạn sẽ nhận ra đây không phải là trường hợp (đặc biệt là vì bạn không chắc 'd đếm số nút bị mờ và nhận ra rằng có nhiều hơn 26).

Bạn cũng có thể nghĩ rằng không thể tương tác với các nút bị mờ đi, nhưng chúng hoàn toàn có thể. Nếu bạn nhấp vào nút mờ đầu tiên, thì tiêu điểm sẽ được đặt vào phần tử đầu tiên trong hàng phim thứ hai và bạn sẽ nghe thấy VoiceOver thông báo “Liên kết: Thời gian phiêu lưu”.

Nhưng các nút này nằm bên trong các phần tử liên kết. Tại sao một nút lại nằm bên trong một liên kết, tôi không biết, vì tôi không phải là một phần của quá trình phát triển, nhưng tôi có thể cho rằng ai đó nghĩ rằng chúng nên bị vô hiệu hóa đối với trình đọc màn hình vì họ đặt aria-disabled="true"thuộc tính vào chúng, mà không xem xét thực tế là gì hiệu quả của việc làm như vậy sẽ có trên UX.

Nút bị tắt bên trong một phần tử liên kết

Trong ảnh chụp màn hình ở trên, bạn có thể thấy rằng liên kết đến Adventure Timearia-disabled="false"và nó kết thúc bằng một divđiều role="button"đó aria-disabled. Điều này hiển thị trong danh sách các nút bị mờ của chúng tôi.

Tôi cũng sẽ lưu ý, bởi vì nó hơi tức giận, rằng có một nút khác bên trong liên kết. Nút này không bị tắt mà thay vào đó được đánh dấu bằng aria-hidden="true", vì vậy trình đọc màn hình hoàn toàn không thể tương tác với nó. cái nút này để làm gì? Nó cho phép bạn thêm phương tiện vào danh sách yêu thích của mình.

Nút ẩn thêm phương tiện vào danh sách yêu thích của bạn

Thật thú vị, nó có một nhãn aria cho bạn biết mục đích của nó, mặc dù thực sự nó nên nói một cái gì đó như “Thêm thời gian phiêu lưu vào danh sách của tôi”.

Ồ, khoan đã - tôi đã tham gia vào mọi thứ sai sót với giao diện người dùng nhỏ này đến nỗi tôi đã quên nói về bảng thuật ngữ!

Như bạn có thể thấy, các nút bị mờ không phải là phần của bảng thuật ngữ; thay vào đó, chúng không được hiển thị dưới dạng các nút, chúng chỉ là văn bản thẳng lên.

Các nút chỉ là văn bản

Nếu bạn quản lý để điều hướng đến danh sách các chữ cái mà bạn có thể nhấp vào và đến đầu tiên trong số các mục nhập bắt đầu bằng chữ cái bạn đã nhấp, bạn sẽ chỉ nghe thấy “A,” “B”, “C”, v.v. khi bạn điều hướng qua chúng. Hơn nữa, nó không thông báo cho người dùng trình đọc màn hình rằng các chữ cái họ đang nghe là có thể nhấp được!

Vì vậy, tóm lại, đôi khi thấy một thứ hoàn toàn không sử dụng được để cân nhắc xem cần phải làm gì để biến thứ gì đó trở nên hữu ích.

Cách xây dựng bảng thuật ngữ có thể truy cập được

Bây giờ chúng ta đã dành nhiều thời gian để nói về lý do tại sao tôi viết bài này và đưa ra các ví dụ về bảng thuật ngữ tốt và những bảng thuật ngữ hoàn toàn không tốt, tôi nghĩ đã đến lúc bắt đầu viết mã - nghĩa là chúng ta sẽ nhận được vào các công cụ chúng tôi cần để triển khai những gì chúng tôi cho là tốt.

Đầu tiên, tôi sẽ nói về một số phần rất cụ thể của mã, và sau đó, khi chúng ta bắt đầu triển khai, chúng ta sẽ thảo luận về mã tổng thể.

Sử dụng CSS cho nội dung có thể truy cập thân thiện với trình đọc màn hình

Một điều mà hầu hết mọi người sẽ cần nếu họ đang cố gắng làm cho bất kỳ phần nào trên trang web của họ có thể truy cập được là một cách để chỉ hiển thị một số nội dung cho người đọc màn hình. Thực tế là, nhiều điều cần được giải thích cho người dùng bị khiếm thị về thị giác mà có thể thấy rõ ràng từ ngữ cảnh trực quan. Bài viết này từ WebAim đề cập đến nhiều cách khác nhau để ẩn và hiển thị nội dung cho trình đọc màn hình bằng cách sử dụng CSS.

Một điều rõ ràng cần lưu ý là các phương pháp để hiển thị nội dung cho trình đọc màn hình (nhưng ẩn chúng khỏi người dùng khác) đều là hack. Theo ý kiến ​​của tôi, thật không may là không có thuộc tính chỉ dành cho aria hoặc một giải pháp tương tự để chúng tôi không liên quan đến những vụ hack này, vì hack có những hành vi không tối ưu. Ví dụ: giải pháp phổ biến nhất là đặt nội dung chỉ dành cho trình đọc màn hình trong phần của DOM nơi chúng ta muốn nó được nhìn thấy và sử dụng CSS để di chuyển nó ra khỏi chế độ xem hiển thị. Điều này có tác dụng phụ là khiến mọi người bối rối khi điều hướng qua bàn phím vì các phần tử có thể lấy tiêu điểm sẽ vẫn nằm trong luồng điều hướng, nhưng nằm ngoài tầm nhìn của họ.

Tất cả những gì đã nói, chúng tôi sẽ sử dụng CSS sau, được mượn từ bài viết WebAim được liên kết ở trên, cho lớp chỉ trình đọc màn hình của chúng tôi:

.sr-only {
    position:absolute;
    left:-10000px;
    top:auto;
    width:1px;
    height:1px;
    overflow:hidden;
}

Bên cạnh đó, chúng tôi sẽ đưa ra một quyết định đi ngược lại các đề xuất chung về khả năng truy cập: làm cho một số nút của chúng tôi trông không giống với các nút.

Tại sao chúng ta lại làm việc này? Bởi vì, về mặt thực dụng, con tàu đó đã ra khơi. Mọi người muốn làm cho các nút trông giống như những thứ khác, nhưng chúng tôi cần chúng trở thành nút vì lợi ích khả năng tiếp cận của họ.

Vì mọi người thường muốn các nút trông không giống nút, tôi sẽ chỉ cho bạn cách sử dụng các nút chưa được định kiểu vẫn có thể truy cập được. Chúng tôi sẽ không sử dụng một lớp nút chưa được định kiểu, nhưng thay vào đó, áp dụng các thuộc tính sau cho các nút mà chúng tôi sẽ không tạo kiểu.

{
background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    font: inherit;
    padding: 0;
    outline: inherit;
}

Viết các mục từ thuật ngữ của chúng tôi bằng cách sử dụng Đánh dấu

Chúng tôi sẽ viết các phần của bảng thuật ngữ của chúng tôi dưới dạng danh sách mô tả , đôi khi cũng được gọi là danh sách định nghĩa. Dưới đây là danh sách ví dụ về các mục thuật ngữ dưới chữ A, liên quan đến các công nghệ hỗ trợ:

 

 

Bản thân các thuật ngữ và định nghĩa đã được mượn từ usability.gov .

Bên cạnh đó, như bạn đã biết, chúng tôi sẽ sử dụng các nút để đại diện cho các chữ cái trong bảng thuật ngữ của chúng tôi, trông giống như sau:

<button class='letter' aria-label="Glossary letter A">A</button>

Nỗ lực về bảng chú giải thuật ngữ đầu tiên của chúng tôi

Ở đây, chúng tôi có một nỗ lực đầu tiên đơn giản về một bảng chú giải thuật ngữ. Bảng thuật ngữ bị ẩn, nhưng có một nút cho biết Hiển thị Bảng chú giải thuật ngữ . Khi được nhấp vào, bảng thuật ngữ sẽ hiển thị và nút trở nên vô hình.

 

 

Bảng chú giải thuật ngữ bị ẩn:

Hiển thị nút Bảng chú giải thuật ngữ

Bảng chú giải được hiển thị:

Bảng thuật ngữ mở không có tiêu điểm rõ ràng

Nhưng, tất nhiên, chúng ta cần sử dụng trình đọc màn hình với những gì chúng ta có - và ngay lập tức, có một số thứ không tốt.

Ví dụ, chúng ta có thể thấy rằng không phải mọi chữ cái của chúng ta đều chứa các subitem trong bảng chú giải thuật ngữ vì chúng ta đã tắt các chữ cái không có bất cứ thứ gì bên dưới chúng. Nhưng làm thế nào để những chữ cái đó hiển thị với trình đọc màn hình?

Bên dưới, bên trái, bạn có thể thấy một số nút bị vô hiệu hóa này; ở bên phải là menu Điều khiển biểu mẫu rô-to web cho trang.

Các nút bị tắt ở bên trái và biểu mẫu rôto web ở bên phải

Thật là khó chịu. Các nút bị tắt vẫn hiển thị trong Điều khiển biểu mẫu, có nghĩa là nếu ai đó định nghe tất cả các nút có sẵn, họ cũng sẽ nghe thấy các nút bị mờ này.

Đúng là họ có thể nghe thấy rằng nút bị mờ đi, nhận ra rằng chữ cái đó không cho phép tương tác và cho rằng đó là vì nó không có bất kỳ mục nào trong bảng chú giải thuật ngữ. Nhưng có vẻ khó khăn để truyền đạt thông tin đó theo cách đó.

Hơn nữa, không có cách nào nhanh chóng để truy cập nội dung bảng thuật ngữ đã mở, hiện tại thực tế; do đó, nếu bạn bắt đầu xem qua bảng thuật ngữ bằng trình đọc màn hình của mình, bạn sẽ phải đọc từng nút trước, trước khi đi đến nội dung.

Điều này cũng áp dụng nếu bạn nhấp vào một trong các nút, giả sử nút B. Bạn sẽ vẫn phải đi qua tất cả các nút của bảng chữ cái trước khi bạn đến các thuật ngữ thuật ngữ bạn đã hiển thị khi bạn nhấp vào chữ B.

Cuối cùng, hầu hết các trình đọc màn hình hiển thị các hành vi khác nhau khi tương tác với nội dung trong trình duyệt so với khi người dùng tương tác trực tiếp với nội dung đó. Ví dụ ở đây là bảng thuật ngữ trông như thế nào khi VoiceOver được sử dụng để nhấp vào nút Hiển thị bảng chú giải thuật ngữ :

Sử dụng VoiceOver để mở bảng thuật ngữ

Đúng vậy, bảng thuật ngữ được hiển thị, nhưng tiêu điểm vẫn nằm ở nút hiện đã bị ẩn.

Điều tương tự cũng xảy ra ở đây khi bạn nhấp vào nút Đóng bảng chú giải thuật ngữ .

Nút Đóng bảng chú giải thuật ngữ khi có tiêu điểm

Cuối cùng, nếu bạn không phải là người dùng trình đọc màn hình nhưng đang sử dụng bàn phím để điều hướng giữa các phần tử, các nút chưa được định kiểu của chúng tôi không hiển thị đầy đủ cài đặt tiêu điểm.

Xóa các tính năng không sử dụng được khỏi trình đọc màn hình

Ở đây, tôi khuyên chúng ta nên xóa các phần của bảng thuật ngữ không thể sử dụng được khỏi trình đọc màn hình.

Hãy khắc phục những vấn đề này. Đây là phiên bản tiếp theo của chúng tôi:

 

 

Đầu tiên, hãy giải quyết những thứ dễ bị treo thấp: thêm một kiểu lấy nét đẹp cho nút Đóng và các chữ cái.

Nút Đóng , khi được lấy tiêu điểm, sẽ có nền màu xanh nước biển và chữ X màu trắng.

Nút đóng có dấu X màu trắng và nền xanh nước biển

Các chữ cái có cùng kiểu dáng trong một nút tròn, nhưng có thêm một số phần đệm để mang lại trải nghiệm tuyệt vời khi chúng hiện ra.

.letter:focus {
  text-decoration: none;
  border: 2px solid #000;
  border-radius: 300px;
  padding-left: 10px;
  padding-right: 5px;
  padding-top: 2px;
}

.letter:focus ,.close:focus {
  outline: blue;
  background-color: navy;
  color: white;
}

Tập trung vào chữ cái hiện tại trong bảng chú giải thuật ngữ

Xóa các nút đã tắt khỏi chế độ xem trình đọc màn hình

Thứ hai, hãy loại bỏ tất cả các nút bị vô hiệu hóa. Điều này đủ dễ dàng để làm; nếu chúng bị vô hiệu, chúng tôi cũng có thể cung cấp cho chúng một aria-hidden="true"thuộc tính.

Rõ ràng, cả phần bảng chú giải thuật ngữ và tiêu đề cho những phần đó chỉ nên có sẵn khi bức thư đó đã được truy cập. Nếu không, chúng ta sẽ gặp phải vấn đề mà chúng ta đã thảo luận trước đó là có quá nhiều nội dung để điều hướng một cách hiệu quả.

Các vấn đề chính của chúng tôi sẽ là tập trung vào các yếu tố và khiến trình đọc màn hình tuân theo sự tập trung của chúng tôi trong các kết hợp trình duyệt khác nhau.

Chúng ta có hai tình huống mà chúng ta cần thay đổi trọng tâm:

  1. Khi chúng tôi mở bảng thuật ngữ, chúng tôi muốn chuyển tiêu điểm ra khỏi nút Hiển thị bảng chú giải thuật ngữ sang nội dung bảng thuật ngữ thực tế
  2. Khi chúng ta nhấp vào một ký tự thuật ngữ, chúng tôi muốn chuyển tiêu điểm vào nội dung của bức thư đó

Khi nhìn vào bảng chú giải, bạn có thể thấy nội dung chữ A ở bên phải bảng chú giải. Khi bạn chuyển đến chữ B tiếp theo và nhấp vào, bạn sẽ thấy nội dung bên phải được thay thế bằng nội dung cho chữ B.

Tuy nhiên, nếu bạn đang sử dụng trình đọc màn hình và bị tắt trực quan đến mức bạn không thể nhìn thấy nội dung xuất hiện ở bên phải, khi bạn đang duyệt bằng chữ A và nhấp vào chữ B, bạn sẽ không có quyền truy cập vào nội dung.

Đây là lý do tại sao điểm thứ hai là quan trọng. Nếu bạn không đặt trọng tâm vào nội dung hiển thị, bạn sẽ phải điều hướng qua toàn bộ danh sách để đi vào nội dung! Điều đó sẽ rất khó chịu.

Để cho phép điều hướng vào nội dung thư, hãy đặt tiêu đề ở đầu mỗi phần để bạn có thể sử dụng điều hướng tiêu đề để đến đó nhanh chóng. Sau đó, đặt tiêu điểm bên trong phần bảng thuật ngữ khi bạn nhấp vào một chữ cái. Bên trong của tiêu đề là một nút để chuyển đến chữ cái tiếp theo.

Làm việc với VoiceOver trong Safari

Các phiên bản Safari khác nhau có thể gặp khó khăn khi thay đổi tiêu điểm thành các phần tử khác dựa trên sự kiện nút liên quan đến VoiceOver. Có một số giải pháp thay thế cho điều này, chẳng hạn như sử dụng một phần tử A hoạt động như một liên kết cục bộ có vai trò attribute="button"hoặc, như tôi đã làm trong mã cho bài viết này, chạy mã tiêu điểm của bạn trong một setTimeoutvới lớn hơn 0ms. Tôi đã làm điều đó với setTimeout 16ms để đặt nó lên trên lần lặp tiếp theo của vòng lặp sự kiện (tất nhiên, với các điều khoản thông thường được áp dụng).

Tất nhiên, nếu điều này được thực hiện trong React hoặc dự án tương tự, chúng tôi có thể hiển thị các thành phần dựa trên các thay đổi trạng thái từ các sự kiện nhấp chuột và trong trường hợp đó, chúng tôi có thể quyết định sử dụng autofocusthuộc tính trên các phần tử mà chúng tôi muốn tập trung vào, nhưng trong trường hợp này, chúng tôi sẽ đặt tiêu điểm động bằng JavaScript.

Vì vậy, tôi nghĩ rằng chúng tôi đã làm điều gì đó hợp lý. Để chứng minh điều đó, tôi sẽ hiển thị một số ảnh chụp màn hình về cách tôi mong đợi người dùng trình đọc màn hình (trong trường hợp này là sử dụng VoiceOver) sẽ điều hướng bảng thuật ngữ.

Đầu tiên, chúng tôi vào trang bằng VoiceOver. Nếu bạn nhấn tổ hợp phím VoiceOver (CTRL-option-U), bạn sẽ thấy như sau:

Vào trang bằng tổ hợp phím VoiceOver

Điều này không thú vị khi nhìn vào, nhưng nó cho bạn thấy rằng bạn có hai cách để truy cập nút thuật ngữ. Nhấn phím VO + phím xuống sẽ chọn nút thuật ngữ:

Bảng thuật ngữ khi bị ẩnNhấp vào nó và bảng thuật ngữ sẽ hiển thị với tiêu điểm của chúng tôi được đặt trên tiêu đề cho nội dung chữ A.

Bảng thuật ngữ khi được hiển thị

Như bạn có thể thấy, VoiceOver sẽ hiển thị các phần mà nó hiện đang được tập trung do con trỏ VoiceOver đang được bật . Đối với mục đích phát triển, tôi nghĩ rằng nó thực sự hữu ích và nói chung, nhiều người dùng trình đọc màn hình không bị mù sử dụng con trỏ để giúp theo dõi trực quan vị trí của họ trên một trang.

Khi chúng ta mở bảng thuật ngữ và xem lại Điều khiển biểu mẫu, chúng ta có thể thấy rằng chỉ các nút không bị vô hiệu hóa của chúng tôi mới có sẵn vì chúng tôi đã thêm aria-hidden="true"vào mọi nút cũng bị vô hiệu hóa.

Chỉ các nút không bị vô hiệu hóa mới hiển thị

Với điều này, người dùng quen thuộc với bảng thuật ngữ của chúng tôi trên một trang mà nó được tìm thấy có thể mở bảng thuật ngữ, truy cập trực tiếp vào Điều khiển biểu mẫu và điều hướng xuống chữ cái họ muốn mà không cần phải đi qua tiêu đề, nút đóng, phần văn bản và vân vân.

Bạn sẽ nhận thấy rằng chúng tôi có nút Đi tới Thư tiếp theo . Ở đây, nó phụ thuộc vào việc bạn theo dõi ngữ cảnh của mình nếu bạn muốn sử dụng nó, vì vậy người ta có thể muốn hoàn toàn không sử dụng nó hoặc thêm nhiều nội dung hơn, chẳng hạn như thay đổi nhãn thành Chuyển sang Chữ cái Tiếp theo (B) , giả sử nút đang hoạt động là A.

Đây là điểm mà tính chung chung phải nhường chỗ cho cách bạn muốn trang web của mình hoạt động, theo cách tương tự như vậy, các thành phần chung sẽ có kiểu thay đổi để phù hợp với giao diện tổng thể của trang web.

Khi người dùng chọn một nút từ menu Điều khiển biểu mẫu, họ sẽ kết thúc với nút đó được chọn trên trang.

Bảng thuật ngữ mở có tiêu điểm nhìn thấy được ở chữ DTại thời điểm này, họ có thể nhấp vào nút, hiển thị các định nghĩa cho chữ cái đó và đặt tiêu điểm cho chữ cái đó.

Các định nghĩa được hiển thị với trọng tâm rõ ràng về chữ cái được chỉ định

Chúng ta có thể thấy rằng trong khi không có h2 nhìn thấy, chúng tôi đã tập trung vào nó và trình đọc màn hình đã đọc nó cho người dùng. Nếu họ điều hướng đến bước tiếp theo, họ sẽ nhận được:

Nút Đi tới Thư tiếp theo chung của chúng tôi

Giới hạn điều hướng đối với trình đọc màn hình và trình quay trang web

Đây là một lần nữa, trong một vấn đề quan điểm. Có một số vấn đề bạn có thể thấy khi lựa chọn nút Đi tới Thư tiếp theo và những vấn đề này có thể khiến việc loại bỏ hoàn toàn hoặc thay đổi vị trí của nó trong DOM đáng được xem xét.

Vấn đề đầu tiên là chúng tôi không có nút Chuyển đến Thư tiếp theo có thể nhìn thấy, có nghĩa là những người sử dụng trình đọc màn hình có thể nhìn thấy có thể bị nhầm lẫn bởi bước này. Tất nhiên, chúng tôi cũng không có tiêu đề trước đó, nhưng điều đó ít có vấn đề hơn vì khi thêm những thứ này vào mà người ta không thể nhìn thấy, tốt nhất là để nó bám sát bối cảnh trực quan nhất có thể. Không quá mất phương hướng để xem hoặc nghe về tiêu đề bên dưới chữ cái bạn đã nhấp vào vì có thể được thông báo là có một nút ở đó để nhấp vào mà không thể nhìn thấy nút như vậy.

Vì ví dụ này có các bảng chú giải thuật ngữ ngắn như vậy, nên có thể có nút Đi tới Chữ cái Tiếp theo ở cuối mỗi phần của điều khoản hoặc bạn có thể quyết định xóa nó hoàn toàn và nhờ mọi người sử dụng rô-to web của trình đọc màn hình của họ để chuyển đến nút tiếp theo, sẽ hoạt động tốt như nhau nếu bạn có ít định nghĩa hoặc nhiều.

Người dùng có thể nhầm lẫn khi đặt nút Đi tới Chữ cái Tiếp theo trước các định nghĩa vì người dùng thực sự mù có thể nghĩ rằng điều đó có nghĩa là không có thuật ngữ nào được định nghĩa cho chữ cái đó.

Cuối cùng, có một hạn chế của nút Đi tới Thư tiếp theo như được trình bày trong rôto:

Hạn chế của việc có nút Đi tới Thư tiếp theo

Khi sử dụng rôto, bạn không được biết ký tự tiếp theo sẽ là gì hoặc thậm chí là ký tự hiện tại là gì.

Cải thiện điều hướng

Có thể có lợi khi nút Bảng chú giải thuật ngữ hiện tại cho biết đó có phải là chữ cái đang được hiển thị hay không, tức là văn bản có nội dung là nút Hiện đang hiển thị chữ cái A trong bảng chú giải thuật ngữ và nút Chuyển đến chữ cái tiếp theo cho biết nút Chuyển đến chữ cái tiếp theo, nút B.

Do đó, nếu bạn đang điều hướng xuống danh sách các nút trong rôto, bạn có hai nơi sẽ dễ dàng đặt ngữ cảnh của bạn.

Tôi sẽ thực hiện những thay đổi đó, có thể thấy ở đây:

 

 

Vì các nút Đi tới Tiếp theo đều nằm trong đánh dấu, nên tùy thuộc vào bất kỳ mã nào bạn đang sử dụng để tạo ra đánh dấu của mình để tạo ra mã đó (cho dù là mẫu, React, Vue hay chỉ làm bằng tay). Thay đổi có liên quan duy nhất là trong switchSelectedLettershàm, được gọi bất cứ khi nào bạn nhấp vào một trong các nút bảng thuật ngữ, như được hiển thị bên dưới:

const switchSelectedLetters = (target) => {
  const selector = "selectedLetter";
  const currentSelectedLetter = document.querySelector(`.${selector}`);
  const currentAria = currentSelectedLetter.getAttribute("aria-label");
  const targetAria = target.getAttribute("aria-label");
  const selectionText = "Current selected, ";
  //use [...selectionText] because we want number of characters, not code units.
  currentSelectedLetter.setAttribute("aria-label", currentAria.substring([...selectionText].length))
  currentSelectedLetter.classList.remove(selector);
  target.setAttribute("aria-label", selectionText + targetAria);
  target.classList.add(selector);
}

Hãy tiếp tục với những thay đổi này và sử dụng lại bảng thuật ngữ. Bạn được thông báo rằng nút thuật ngữ bạn đang truy cập là nút hiện được chọn.

Nút Đi tới Thư tiếp theo mới của chúng tôi

Khi bạn nhấp vào nút Tiếp theo , nút này sẽ trở thành nút hiện được chọn và bạn có thể thấy nút này trong rôto. Hơn nữa, nút Go to Next Letter cũng cho bạn biết chữ cái tiếp theo sẽ là gì.

Màn hình Bảng điều khiển biểu mẫu bảng thuật ngữ cuối cùng, có thể truy cập của chúng tôi

Tôi nghĩ rằng, cuối cùng, việc triển khai này mang lại cho chúng ta một số tính năng hay để tạo ra một bảng thuật ngữ định nghĩa có thể sử dụng và dễ tiếp cận sẽ mang lại lợi ích không chỉ cho những người dùng khiếm thị mà còn cả những người dùng trình duyệt màn hình khác.

Điều chỉnh bảng thuật ngữ có thể truy cập của chúng tôi cho những người dùng gặp khó khăn về tính di động

Cuối cùng, tôi sẽ nhanh chóng chỉ ra cách mọi thứ có thể truy cập được đối với những người dùng khó khăn về tính di động, những người chủ yếu sử dụng bàn phím để điều hướng.

Nút Hiển thị Bảng chú giải thuật ngữ có thể lập tab được và cho biết khi nào nó được lấy tiêu điểm:

Nút Hiển thị Bảng chú giải thuật ngữ khi được gắn thẻ

Nhấp vào nút sẽ mở bảng thuật ngữ:

Mở bảng thuật ngữ bằng phím tabNhấn lại Tab để chọn nút Đóng :

Đóng nút được chọn bằng Tab

Tab tiếp theo chọn một chữ cái:

Nhấn lại tab để chọn chữ cái tiếp theo

Nếu bạn tab, bạn sẽ chuyển đến chữ cái tiếp theo. Sau đó, bạn có thể nhấp vào để xem định nghĩa của chữ cái và nếu bạn nhấn tab sau đó, bạn sẽ ở lại Đóng chữ cái , vì vậy bạn có thể đóng bất kỳ lúc nào khá nhanh. Bạn có thể muốn thêm một trình xử lý cho phím Escape, trong trường hợp này, để cho phép đóng bảng thuật ngữ bằng cách nhấn phím Escape, nhưng hiện tại, nó có thể sử dụng được và tôi nghĩ là có thể hiểu được về mặt logic.

Sự kết luận

Làm cho một thứ gì đó có thể truy cập được không đặc biệt khó, miễn là bạn có thể hình dung ra những vấn đề mà khách hàng của bạn sẽ gặp phải và ghi nhớ những giới hạn và mô hình của thế giới mà các công nghệ hỗ trợ khác nhau phải hoạt động.

 

Nguồn: https://blog.logrocket.com/building-accessible-glossary-vanilla-javascript/

#javascript 

What is GEEK

Buddha Community

Xây Dựng Bảng Thuật Ngữ Có Thể Truy Cập được Bằng JavaScript Vani
Trung  Nguyen

Trung Nguyen

1657899960

Xây Dựng Bảng Thuật Ngữ Có Thể Truy Cập được Bằng JavaScript Vani

Đây là lần đầu tiên tôi viết một bài báo như thế này. Hầu hết các bài viết của tôi đều bắt nguồn từ một ý tưởng mà tôi có và sau đó tôi thực hiện nghiên cứu để làm cho nó hoạt động, nhưng bài viết này được lấy cảm hứng từ một dự án gần đây mà tôi đã thực hiện với nền tảng học tập điện tử Kognity , người đã quan tâm đến việc cung cấp cho người dùng của họ trải nghiệm trợ năng hàng đầu khi sử dụng nền tảng của họ.

Trong số nhiều phần của nền tảng mà chúng tôi có thể truy cập được là bảng chú giải thuật ngữ tương tác từ sách giáo khoa của họ có sẵn dưới dạng thanh bên có thể mở rộng / thu gọn trên nền tảng trực tuyến của họ. Vì chúng tôi đã có một kinh nghiệm thực sự tốt trong việc xây dựng một giải pháp thành công, dễ tiếp cận, nên tôi muốn chia sẻ nó.

Giải pháp Kognity được viết bằng Vue.js, nhưng phần lớn chức năng của nó là dành riêng cho nền tảng của họ - và bởi vì tôi muốn làm cho mọi thứ càng chung chung càng tốt cho bài đăng này - tôi sẽ triển khai một giải pháp tương tự trong vanilla JavaScript. Sẽ dễ dàng làm lại việc triển khai này cho nhiều khung công tác khác.

Lưu ý về ảnh chụp màn hình của bài viết này và cách sử dụng trình đọc màn hình

Có thể có sự khác biệt đáng kể giữa trình đọc màn hình và kết hợp trình duyệt và nhiều ảnh chụp màn hình trong bài viết này sẽ hiển thị cách hoạt động của trình đọc màn hình. Tôi chủ yếu sử dụng máy Mac và do đó hầu hết các ảnh chụp màn hình của tôi sẽ sử dụng VoiceOver trên Firefox, Chrome và Safari. Tuy nhiên, mã được trình bày trong bài viết này đã được thử nghiệm với NVDA và Firefox trên Windows. Trong những trường hợp có sự khác biệt về hành vi, sự khác biệt đó được ghi nhận.

Do những khác biệt đáng kể này, bạn có thể muốn xem xét sử dụng một giải pháp như Assistiv Labs để thử nghiệm vì họ có thể cung cấp cho máy ảo các thiết lập trình đọc màn hình khác nhau mà bạn có thể truy cập từ xa. Trong bất kỳ trường hợp nào, sẽ là sai lầm nếu chỉ kiểm tra mã này trên một tổ hợp trình đọc màn hình / trình duyệt vì sự khác biệt lớn trong đầu ra và khả năng của chúng, và bạn có thể dễ dàng bỏ lỡ các vấn đề.

Khám phá các ví dụ về bảng chú giải thuật ngữ

Bảng chú giải thuật ngữ Kognity

Vì vậy, trước tiên, chúng ta hãy xem cách hoạt động của bảng thuật ngữ Kognity. Trong ảnh chụp màn hình sau, bạn có thể thấy một phần của sách giáo khoa sinh học Kognity và nút để mở bảng chú giải thuật ngữ ở góc trên bên phải.

Bảng chú giải thuật ngữ Kognity

Khi bạn nhấp vào nút bảng thuật ngữ, bảng thuật ngữ sẽ mở ra và bạn thấy một cái gì đó giống như sau:

Bảng thuật ngữ Kognity khi mở

 

Bạn sẽ thấy một số chữ cái trong bảng chú giải bị chuyển sang màu xám - đây là những chữ cái không có bất kỳ mục nào liên quan đến phần cụ thể này của sách giáo khoa. Như bạn có thể thấy, chữ A có một vòng tròn màu xanh mòng két xung quanh nó để chỉ ra rằng đó là chữ cái được chọn khi bảng chú giải lần đầu tiên mở ra (tất nhiên, giả sử rằng có các mục dưới chữ A).

Có một số chức năng bổ sung được liên kết với bảng thuật ngữ này, chẳng hạn như lọc theo kiểu nhập văn bản; Tôi sẽ không triển khai chức năng tương tự trong bài viết này, nhưng sẽ đề cập đến nó cho đầy đủ.

Bảng chú giải thuật ngữ tiêu đề phim HBOMax

Tôi chắc rằng bạn đã từng thấy điều gì đó như thế này trước đây: các chữ cái trong bảng chữ cái được liệt kê ra và việc nhấp vào một trong các chữ cái sẽ hiển thị cho bạn một số nội dung liên quan đến chữ cái đó. Trong trường hợp này, đó là một bảng thuật ngữ, nhưng bạn thấy một mẫu giao diện người dùng tương tự để điều hướng các dịch vụ video, ví dụ ở đây trên HBOMax:

Màn hình tiêu đề HBOMax

Nếu bạn nhấp vào một trong các chữ cái ở thanh bên bên phải, trang sẽ cuộn xuống bộ phim đầu tiên có tiêu đề bắt đầu bằng chữ cái đó.

Vì vậy, tôi đoán chúng ta có thể đồng ý rằng đó là một thiết kế phổ biến, nhưng điều ít phổ biến hơn là một thiết kế dễ hiểu và dễ tiếp cận. Chúng tôi sẽ chứng minh điều này nhiều hơn một chút với ví dụ HBOMax này trong phần tiếp theo.

Tạo bảng thuật ngữ có thể truy cập được: Cách tiếp cận

Về bản chất, khả năng tiếp cận là một vấn đề về trải nghiệm người dùng, và mọi nhà phát triển và nhà thiết kế phải sử dụng trí tưởng tượng của họ để vật lộn với nó, giống như họ phải làm với bất kỳ việc sử dụng ứng dụng nào của họ. Bất kể bạn có thể có bộ khả năng cụ thể nào, bộ đó sẽ không phù hợp với tất cả người dùng của bạn.

Hành động tưởng tượng này về cơ bản là chìa khóa để tạo ra một ứng dụng có thể truy cập hợp lý, nhưng hãy lưu ý. Tôi nói có thể truy cập hợp lý để nhấn mạnh rằng, mặc dù có những phần sẽ rất khó, nỗ lực lập trình cần thiết để làm cho ứng dụng có thể truy cập được là rất nhỏ, miễn là bạn đã thực hiện công việc cần thiết là hình dung cách ứng dụng sẽ được sử dụng trong trường hợp khả năng của ai đó có lẽ khác xa với khả năng của bạn. Và thông thường, công việc cần thiết của trí tưởng tượng cũng không đặc biệt tiêu hao!

Xây dựng hồ sơ người dùng của chúng tôi

Đầu tiên, hãy hình dung cách người dùng với các nhóm khả năng cụ thể, khác nhau sẽ sử dụng nội dung và công cụ để tương tác với nội dung trên trang web của bạn. Có một bộ hồ sơ người dùng có thể hữu ích. Để xây dựng bảng thuật ngữ của chúng tôi, chúng ta sẽ hình dung ba cấu hình riêng biệt, như sau:

Hồ sơ người dùng 1: Người dùng không sử dụng bất kỳ thiết bị và kỹ thuật hỗ trợ nào

Điều này bao gồm những người không sử dụng thiết bị hoặc kỹ thuật hỗ trợ, nhưng vẫn có thể cần chúng hoặc thiếu một số công suất mà không dễ sửa chữa bằng các thiết bị sửa chữa. Vì vậy, ngoài người hoàn toàn không gặp bất kỳ vấn đề gì, trong danh mục này, chúng tôi sẽ đặt:

Chúng tôi có thể coi đây là người dùng bình thường cơ bản của chúng tôi.

Hồ sơ người dùng 2: Những người khuyết tật vận động

Điều này bao gồm những người chỉ sử dụng bàn phím và phím tắt tab để điều hướng một trang web, tức là những người không có khả năng sử dụng chuột hoặc bàn di chuột.

Hồ sơ người dùng 3: Những người sử dụng trình đọc màn hình

Có một số người có thể phù hợp với mô tả này. Có những người có thể nhìn thấy trang đủ tốt để tương tác mà không cần trình đọc màn hình, chẳng hạn như những người mắc chứng khó đọc hoặc khó xử lý ngôn ngữ khác, nhưng lại thích sử dụng trình đọc màn hình để được trợ giúp. Sau đó, có những người gặp khó khăn về thị giác không chính thức bị mù vẫn có thể thích sử dụng trình đọc màn hình để giúp họ. Cuối cùng, có những người dùng bị mù và hoàn toàn cần một trình đọc màn hình.

Bạn có thể đọc bảng phân tích thống kê sử dụng trình đọc màn hình từ Khảo sát người dùng trình đọc màn hình WebAim lần thứ chín , được cập nhật lần cuối vào ngày 30 tháng 6 năm 2021.

Làm thế nào để những người dùng khác nhau này sử dụng cùng một trang web?

Các nhà phát triển chưa quen với việc kiểm tra các vấn đề về khả năng tiếp cận quyết định kiểm tra cách mọi thứ hoạt động bằng cách lướt qua nó. Nếu bạn có thể nhấp vào các thứ, tương tác với chúng và đảm bảo chúng hoạt động chính xác, thì giả định rằng trang web có thể truy cập được.

Chắc chắn là một yêu cầu đối với khả năng truy cập là tất cả các yếu tố tương tác phải đạt được bằng phím tab, nhưng đó là yêu cầu chủ yếu đối với người dùng của chúng tôi trong nhóm hai, vì việc sử dụng phím tab sẽ phù hợp với những người có vấn đề về di động cũng có thể xử lý trực quan nội dung của trang.

Tuy nhiên, người dùng trình đọc màn hình yêu cầu các cách khác để sắp xếp và xử lý nội dung của trang và chúng tôi nên xem xét điều này trong giải pháp của mình.

Thiết kế rô-to web để sử dụng trình đọc màn hình

Cụ thể, mọi trình đọc màn hình đều có một cách để đọc các phần hữu ích của trang riêng biệt với thứ tự trang bình thường. Điều này hữu ích để tìm những gì bạn muốn làm trên một trang web và điều hướng đến các phần của trang mà bạn quan tâm.

Ví dụ, trong VoiceOver, đây được gọi là rô-to web (hoặc chỉ rô-to). Dưới đây là hình ảnh của rôto trên Kognity với bảng chú giải thuật ngữ đã đóng.

Rotor web Điều khiển biểu mẫu từ VoiceOver trên trang Kognity

Điều đầu tiên bạn sẽ nhận thấy là chỉ có 13 điều khiển biểu mẫu với nút thuật ngữ đóng. Thật tuyệt! Hãy tưởng tượng nếu bạn đang tương tác với cái này khi nó đang mở: sẽ có 12 nút, cộng với 26 nút cho bảng chữ cái tiếng Anh, tổng cộng có 38 mục để đọc. Đó là rất nhiều! Và, trong trường hợp của những người trong nhóm người dùng 3 có một chút thị giác, tất nhiên họ sẽ có thể sử dụng chế độ xem của phần tử trình đọc màn hình một cách trực quan.

Tại sao chúng tôi tạo một bảng thuật ngữ có thể truy cập được?

Để đảm bảo rằng mọi người có thể sử dụng tối ưu bảng thuật ngữ trên trang của chúng tôi, chúng tôi nên thiết kế một quy trình làm việc hợp lý. Nếu quy trình tương tác với trang không được suy nghĩ kỹ lưỡng, trang của chúng tôi sẽ không thể sử dụng được.

Để làm ví dụ về việc triển khai có vấn đề về khả năng tiếp cận, tôi sẽ chọn một chút về HBOMax. Tôi không có bất cứ điều gì chống lại họ (mặc dù tôi đã hy vọng có nhiều nội dung Warner Brothers cổ điển hơn), nhưng tôi vừa có tư cách thành viên và tôi nhận thấy những điều này bởi vì tôi là một nhà phát triển.

Giả sử chúng ta đang ở một trong các trang có điều hướng kiểu bảng thuật ngữ, chẳng hạn như Phim hài A – Z. Nếu chúng tôi đang sử dụng VoiceOver và quyết định kiểm tra rôto, rôto sẽ có sẵn khoảng 38 nút để sử dụng:

Điều khiển biểu mẫu từ VoiceOver trong ứng dụng HBOMax

Chỉ tám trong số các nút này có nhãn có ý nghĩa hoặc một nhãn cho chúng ta cơ hội hiểu chúng làm gì. Phần còn lại của chúng được gắn nhãn nút làm mờ .

“Nút mờ” là cách VoiceOver thông báo rằng một nút hiện đang bị vô hiệu hóa và ứng dụng không thể sử dụng được. Bạn có thể nghĩ rằng các nút bị mờ là để điều hướng các danh mục theo chữ cái đầu tiên của tiêu đề phim, nhưng khi bạn nhấp vào để xem các tiêu đề bắt đầu bằng chữ cái cụ thể đó, bạn sẽ nhận ra đây không phải là trường hợp (đặc biệt là vì bạn không chắc 'd đếm số nút bị mờ và nhận ra rằng có nhiều hơn 26).

Bạn cũng có thể nghĩ rằng không thể tương tác với các nút bị mờ đi, nhưng chúng hoàn toàn có thể. Nếu bạn nhấp vào nút mờ đầu tiên, thì tiêu điểm sẽ được đặt vào phần tử đầu tiên trong hàng phim thứ hai và bạn sẽ nghe thấy VoiceOver thông báo “Liên kết: Thời gian phiêu lưu”.

Nhưng các nút này nằm bên trong các phần tử liên kết. Tại sao một nút lại nằm bên trong một liên kết, tôi không biết, vì tôi không phải là một phần của quá trình phát triển, nhưng tôi có thể cho rằng ai đó nghĩ rằng chúng nên bị vô hiệu hóa đối với trình đọc màn hình vì họ đặt aria-disabled="true"thuộc tính vào chúng, mà không xem xét thực tế là gì hiệu quả của việc làm như vậy sẽ có trên UX.

Nút bị tắt bên trong một phần tử liên kết

Trong ảnh chụp màn hình ở trên, bạn có thể thấy rằng liên kết đến Adventure Timearia-disabled="false"và nó kết thúc bằng một divđiều role="button"đó aria-disabled. Điều này hiển thị trong danh sách các nút bị mờ của chúng tôi.

Tôi cũng sẽ lưu ý, bởi vì nó hơi tức giận, rằng có một nút khác bên trong liên kết. Nút này không bị tắt mà thay vào đó được đánh dấu bằng aria-hidden="true", vì vậy trình đọc màn hình hoàn toàn không thể tương tác với nó. cái nút này để làm gì? Nó cho phép bạn thêm phương tiện vào danh sách yêu thích của mình.

Nút ẩn thêm phương tiện vào danh sách yêu thích của bạn

Thật thú vị, nó có một nhãn aria cho bạn biết mục đích của nó, mặc dù thực sự nó nên nói một cái gì đó như “Thêm thời gian phiêu lưu vào danh sách của tôi”.

Ồ, khoan đã - tôi đã tham gia vào mọi thứ sai sót với giao diện người dùng nhỏ này đến nỗi tôi đã quên nói về bảng thuật ngữ!

Như bạn có thể thấy, các nút bị mờ không phải là phần của bảng thuật ngữ; thay vào đó, chúng không được hiển thị dưới dạng các nút, chúng chỉ là văn bản thẳng lên.

Các nút chỉ là văn bản

Nếu bạn quản lý để điều hướng đến danh sách các chữ cái mà bạn có thể nhấp vào và đến đầu tiên trong số các mục nhập bắt đầu bằng chữ cái bạn đã nhấp, bạn sẽ chỉ nghe thấy “A,” “B”, “C”, v.v. khi bạn điều hướng qua chúng. Hơn nữa, nó không thông báo cho người dùng trình đọc màn hình rằng các chữ cái họ đang nghe là có thể nhấp được!

Vì vậy, tóm lại, đôi khi thấy một thứ hoàn toàn không sử dụng được để cân nhắc xem cần phải làm gì để biến thứ gì đó trở nên hữu ích.

Cách xây dựng bảng thuật ngữ có thể truy cập được

Bây giờ chúng ta đã dành nhiều thời gian để nói về lý do tại sao tôi viết bài này và đưa ra các ví dụ về bảng thuật ngữ tốt và những bảng thuật ngữ hoàn toàn không tốt, tôi nghĩ đã đến lúc bắt đầu viết mã - nghĩa là chúng ta sẽ nhận được vào các công cụ chúng tôi cần để triển khai những gì chúng tôi cho là tốt.

Đầu tiên, tôi sẽ nói về một số phần rất cụ thể của mã, và sau đó, khi chúng ta bắt đầu triển khai, chúng ta sẽ thảo luận về mã tổng thể.

Sử dụng CSS cho nội dung có thể truy cập thân thiện với trình đọc màn hình

Một điều mà hầu hết mọi người sẽ cần nếu họ đang cố gắng làm cho bất kỳ phần nào trên trang web của họ có thể truy cập được là một cách để chỉ hiển thị một số nội dung cho người đọc màn hình. Thực tế là, nhiều điều cần được giải thích cho người dùng bị khiếm thị về thị giác mà có thể thấy rõ ràng từ ngữ cảnh trực quan. Bài viết này từ WebAim đề cập đến nhiều cách khác nhau để ẩn và hiển thị nội dung cho trình đọc màn hình bằng cách sử dụng CSS.

Một điều rõ ràng cần lưu ý là các phương pháp để hiển thị nội dung cho trình đọc màn hình (nhưng ẩn chúng khỏi người dùng khác) đều là hack. Theo ý kiến ​​của tôi, thật không may là không có thuộc tính chỉ dành cho aria hoặc một giải pháp tương tự để chúng tôi không liên quan đến những vụ hack này, vì hack có những hành vi không tối ưu. Ví dụ: giải pháp phổ biến nhất là đặt nội dung chỉ dành cho trình đọc màn hình trong phần của DOM nơi chúng ta muốn nó được nhìn thấy và sử dụng CSS để di chuyển nó ra khỏi chế độ xem hiển thị. Điều này có tác dụng phụ là khiến mọi người bối rối khi điều hướng qua bàn phím vì các phần tử có thể lấy tiêu điểm sẽ vẫn nằm trong luồng điều hướng, nhưng nằm ngoài tầm nhìn của họ.

Tất cả những gì đã nói, chúng tôi sẽ sử dụng CSS sau, được mượn từ bài viết WebAim được liên kết ở trên, cho lớp chỉ trình đọc màn hình của chúng tôi:

.sr-only {
    position:absolute;
    left:-10000px;
    top:auto;
    width:1px;
    height:1px;
    overflow:hidden;
}

Bên cạnh đó, chúng tôi sẽ đưa ra một quyết định đi ngược lại các đề xuất chung về khả năng truy cập: làm cho một số nút của chúng tôi trông không giống với các nút.

Tại sao chúng ta lại làm việc này? Bởi vì, về mặt thực dụng, con tàu đó đã ra khơi. Mọi người muốn làm cho các nút trông giống như những thứ khác, nhưng chúng tôi cần chúng trở thành nút vì lợi ích khả năng tiếp cận của họ.

Vì mọi người thường muốn các nút trông không giống nút, tôi sẽ chỉ cho bạn cách sử dụng các nút chưa được định kiểu vẫn có thể truy cập được. Chúng tôi sẽ không sử dụng một lớp nút chưa được định kiểu, nhưng thay vào đó, áp dụng các thuộc tính sau cho các nút mà chúng tôi sẽ không tạo kiểu.

{
background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    font: inherit;
    padding: 0;
    outline: inherit;
}

Viết các mục từ thuật ngữ của chúng tôi bằng cách sử dụng Đánh dấu

Chúng tôi sẽ viết các phần của bảng thuật ngữ của chúng tôi dưới dạng danh sách mô tả , đôi khi cũng được gọi là danh sách định nghĩa. Dưới đây là danh sách ví dụ về các mục thuật ngữ dưới chữ A, liên quan đến các công nghệ hỗ trợ:

 

 

Bản thân các thuật ngữ và định nghĩa đã được mượn từ usability.gov .

Bên cạnh đó, như bạn đã biết, chúng tôi sẽ sử dụng các nút để đại diện cho các chữ cái trong bảng thuật ngữ của chúng tôi, trông giống như sau:

<button class='letter' aria-label="Glossary letter A">A</button>

Nỗ lực về bảng chú giải thuật ngữ đầu tiên của chúng tôi

Ở đây, chúng tôi có một nỗ lực đầu tiên đơn giản về một bảng chú giải thuật ngữ. Bảng thuật ngữ bị ẩn, nhưng có một nút cho biết Hiển thị Bảng chú giải thuật ngữ . Khi được nhấp vào, bảng thuật ngữ sẽ hiển thị và nút trở nên vô hình.

 

 

Bảng chú giải thuật ngữ bị ẩn:

Hiển thị nút Bảng chú giải thuật ngữ

Bảng chú giải được hiển thị:

Bảng thuật ngữ mở không có tiêu điểm rõ ràng

Nhưng, tất nhiên, chúng ta cần sử dụng trình đọc màn hình với những gì chúng ta có - và ngay lập tức, có một số thứ không tốt.

Ví dụ, chúng ta có thể thấy rằng không phải mọi chữ cái của chúng ta đều chứa các subitem trong bảng chú giải thuật ngữ vì chúng ta đã tắt các chữ cái không có bất cứ thứ gì bên dưới chúng. Nhưng làm thế nào để những chữ cái đó hiển thị với trình đọc màn hình?

Bên dưới, bên trái, bạn có thể thấy một số nút bị vô hiệu hóa này; ở bên phải là menu Điều khiển biểu mẫu rô-to web cho trang.

Các nút bị tắt ở bên trái và biểu mẫu rôto web ở bên phải

Thật là khó chịu. Các nút bị tắt vẫn hiển thị trong Điều khiển biểu mẫu, có nghĩa là nếu ai đó định nghe tất cả các nút có sẵn, họ cũng sẽ nghe thấy các nút bị mờ này.

Đúng là họ có thể nghe thấy rằng nút bị mờ đi, nhận ra rằng chữ cái đó không cho phép tương tác và cho rằng đó là vì nó không có bất kỳ mục nào trong bảng chú giải thuật ngữ. Nhưng có vẻ khó khăn để truyền đạt thông tin đó theo cách đó.

Hơn nữa, không có cách nào nhanh chóng để truy cập nội dung bảng thuật ngữ đã mở, hiện tại thực tế; do đó, nếu bạn bắt đầu xem qua bảng thuật ngữ bằng trình đọc màn hình của mình, bạn sẽ phải đọc từng nút trước, trước khi đi đến nội dung.

Điều này cũng áp dụng nếu bạn nhấp vào một trong các nút, giả sử nút B. Bạn sẽ vẫn phải đi qua tất cả các nút của bảng chữ cái trước khi bạn đến các thuật ngữ thuật ngữ bạn đã hiển thị khi bạn nhấp vào chữ B.

Cuối cùng, hầu hết các trình đọc màn hình hiển thị các hành vi khác nhau khi tương tác với nội dung trong trình duyệt so với khi người dùng tương tác trực tiếp với nội dung đó. Ví dụ ở đây là bảng thuật ngữ trông như thế nào khi VoiceOver được sử dụng để nhấp vào nút Hiển thị bảng chú giải thuật ngữ :

Sử dụng VoiceOver để mở bảng thuật ngữ

Đúng vậy, bảng thuật ngữ được hiển thị, nhưng tiêu điểm vẫn nằm ở nút hiện đã bị ẩn.

Điều tương tự cũng xảy ra ở đây khi bạn nhấp vào nút Đóng bảng chú giải thuật ngữ .

Nút Đóng bảng chú giải thuật ngữ khi có tiêu điểm

Cuối cùng, nếu bạn không phải là người dùng trình đọc màn hình nhưng đang sử dụng bàn phím để điều hướng giữa các phần tử, các nút chưa được định kiểu của chúng tôi không hiển thị đầy đủ cài đặt tiêu điểm.

Xóa các tính năng không sử dụng được khỏi trình đọc màn hình

Ở đây, tôi khuyên chúng ta nên xóa các phần của bảng thuật ngữ không thể sử dụng được khỏi trình đọc màn hình.

Hãy khắc phục những vấn đề này. Đây là phiên bản tiếp theo của chúng tôi:

 

 

Đầu tiên, hãy giải quyết những thứ dễ bị treo thấp: thêm một kiểu lấy nét đẹp cho nút Đóng và các chữ cái.

Nút Đóng , khi được lấy tiêu điểm, sẽ có nền màu xanh nước biển và chữ X màu trắng.

Nút đóng có dấu X màu trắng và nền xanh nước biển

Các chữ cái có cùng kiểu dáng trong một nút tròn, nhưng có thêm một số phần đệm để mang lại trải nghiệm tuyệt vời khi chúng hiện ra.

.letter:focus {
  text-decoration: none;
  border: 2px solid #000;
  border-radius: 300px;
  padding-left: 10px;
  padding-right: 5px;
  padding-top: 2px;
}

.letter:focus ,.close:focus {
  outline: blue;
  background-color: navy;
  color: white;
}

Tập trung vào chữ cái hiện tại trong bảng chú giải thuật ngữ

Xóa các nút đã tắt khỏi chế độ xem trình đọc màn hình

Thứ hai, hãy loại bỏ tất cả các nút bị vô hiệu hóa. Điều này đủ dễ dàng để làm; nếu chúng bị vô hiệu, chúng tôi cũng có thể cung cấp cho chúng một aria-hidden="true"thuộc tính.

Rõ ràng, cả phần bảng chú giải thuật ngữ và tiêu đề cho những phần đó chỉ nên có sẵn khi bức thư đó đã được truy cập. Nếu không, chúng ta sẽ gặp phải vấn đề mà chúng ta đã thảo luận trước đó là có quá nhiều nội dung để điều hướng một cách hiệu quả.

Các vấn đề chính của chúng tôi sẽ là tập trung vào các yếu tố và khiến trình đọc màn hình tuân theo sự tập trung của chúng tôi trong các kết hợp trình duyệt khác nhau.

Chúng ta có hai tình huống mà chúng ta cần thay đổi trọng tâm:

  1. Khi chúng tôi mở bảng thuật ngữ, chúng tôi muốn chuyển tiêu điểm ra khỏi nút Hiển thị bảng chú giải thuật ngữ sang nội dung bảng thuật ngữ thực tế
  2. Khi chúng ta nhấp vào một ký tự thuật ngữ, chúng tôi muốn chuyển tiêu điểm vào nội dung của bức thư đó

Khi nhìn vào bảng chú giải, bạn có thể thấy nội dung chữ A ở bên phải bảng chú giải. Khi bạn chuyển đến chữ B tiếp theo và nhấp vào, bạn sẽ thấy nội dung bên phải được thay thế bằng nội dung cho chữ B.

Tuy nhiên, nếu bạn đang sử dụng trình đọc màn hình và bị tắt trực quan đến mức bạn không thể nhìn thấy nội dung xuất hiện ở bên phải, khi bạn đang duyệt bằng chữ A và nhấp vào chữ B, bạn sẽ không có quyền truy cập vào nội dung.

Đây là lý do tại sao điểm thứ hai là quan trọng. Nếu bạn không đặt trọng tâm vào nội dung hiển thị, bạn sẽ phải điều hướng qua toàn bộ danh sách để đi vào nội dung! Điều đó sẽ rất khó chịu.

Để cho phép điều hướng vào nội dung thư, hãy đặt tiêu đề ở đầu mỗi phần để bạn có thể sử dụng điều hướng tiêu đề để đến đó nhanh chóng. Sau đó, đặt tiêu điểm bên trong phần bảng thuật ngữ khi bạn nhấp vào một chữ cái. Bên trong của tiêu đề là một nút để chuyển đến chữ cái tiếp theo.

Làm việc với VoiceOver trong Safari

Các phiên bản Safari khác nhau có thể gặp khó khăn khi thay đổi tiêu điểm thành các phần tử khác dựa trên sự kiện nút liên quan đến VoiceOver. Có một số giải pháp thay thế cho điều này, chẳng hạn như sử dụng một phần tử A hoạt động như một liên kết cục bộ có vai trò attribute="button"hoặc, như tôi đã làm trong mã cho bài viết này, chạy mã tiêu điểm của bạn trong một setTimeoutvới lớn hơn 0ms. Tôi đã làm điều đó với setTimeout 16ms để đặt nó lên trên lần lặp tiếp theo của vòng lặp sự kiện (tất nhiên, với các điều khoản thông thường được áp dụng).

Tất nhiên, nếu điều này được thực hiện trong React hoặc dự án tương tự, chúng tôi có thể hiển thị các thành phần dựa trên các thay đổi trạng thái từ các sự kiện nhấp chuột và trong trường hợp đó, chúng tôi có thể quyết định sử dụng autofocusthuộc tính trên các phần tử mà chúng tôi muốn tập trung vào, nhưng trong trường hợp này, chúng tôi sẽ đặt tiêu điểm động bằng JavaScript.

Vì vậy, tôi nghĩ rằng chúng tôi đã làm điều gì đó hợp lý. Để chứng minh điều đó, tôi sẽ hiển thị một số ảnh chụp màn hình về cách tôi mong đợi người dùng trình đọc màn hình (trong trường hợp này là sử dụng VoiceOver) sẽ điều hướng bảng thuật ngữ.

Đầu tiên, chúng tôi vào trang bằng VoiceOver. Nếu bạn nhấn tổ hợp phím VoiceOver (CTRL-option-U), bạn sẽ thấy như sau:

Vào trang bằng tổ hợp phím VoiceOver

Điều này không thú vị khi nhìn vào, nhưng nó cho bạn thấy rằng bạn có hai cách để truy cập nút thuật ngữ. Nhấn phím VO + phím xuống sẽ chọn nút thuật ngữ:

Bảng thuật ngữ khi bị ẩnNhấp vào nó và bảng thuật ngữ sẽ hiển thị với tiêu điểm của chúng tôi được đặt trên tiêu đề cho nội dung chữ A.

Bảng thuật ngữ khi được hiển thị

Như bạn có thể thấy, VoiceOver sẽ hiển thị các phần mà nó hiện đang được tập trung do con trỏ VoiceOver đang được bật . Đối với mục đích phát triển, tôi nghĩ rằng nó thực sự hữu ích và nói chung, nhiều người dùng trình đọc màn hình không bị mù sử dụng con trỏ để giúp theo dõi trực quan vị trí của họ trên một trang.

Khi chúng ta mở bảng thuật ngữ và xem lại Điều khiển biểu mẫu, chúng ta có thể thấy rằng chỉ các nút không bị vô hiệu hóa của chúng tôi mới có sẵn vì chúng tôi đã thêm aria-hidden="true"vào mọi nút cũng bị vô hiệu hóa.

Chỉ các nút không bị vô hiệu hóa mới hiển thị

Với điều này, người dùng quen thuộc với bảng thuật ngữ của chúng tôi trên một trang mà nó được tìm thấy có thể mở bảng thuật ngữ, truy cập trực tiếp vào Điều khiển biểu mẫu và điều hướng xuống chữ cái họ muốn mà không cần phải đi qua tiêu đề, nút đóng, phần văn bản và vân vân.

Bạn sẽ nhận thấy rằng chúng tôi có nút Đi tới Thư tiếp theo . Ở đây, nó phụ thuộc vào việc bạn theo dõi ngữ cảnh của mình nếu bạn muốn sử dụng nó, vì vậy người ta có thể muốn hoàn toàn không sử dụng nó hoặc thêm nhiều nội dung hơn, chẳng hạn như thay đổi nhãn thành Chuyển sang Chữ cái Tiếp theo (B) , giả sử nút đang hoạt động là A.

Đây là điểm mà tính chung chung phải nhường chỗ cho cách bạn muốn trang web của mình hoạt động, theo cách tương tự như vậy, các thành phần chung sẽ có kiểu thay đổi để phù hợp với giao diện tổng thể của trang web.

Khi người dùng chọn một nút từ menu Điều khiển biểu mẫu, họ sẽ kết thúc với nút đó được chọn trên trang.

Bảng thuật ngữ mở có tiêu điểm nhìn thấy được ở chữ DTại thời điểm này, họ có thể nhấp vào nút, hiển thị các định nghĩa cho chữ cái đó và đặt tiêu điểm cho chữ cái đó.

Các định nghĩa được hiển thị với trọng tâm rõ ràng về chữ cái được chỉ định

Chúng ta có thể thấy rằng trong khi không có h2 nhìn thấy, chúng tôi đã tập trung vào nó và trình đọc màn hình đã đọc nó cho người dùng. Nếu họ điều hướng đến bước tiếp theo, họ sẽ nhận được:

Nút Đi tới Thư tiếp theo chung của chúng tôi

Giới hạn điều hướng đối với trình đọc màn hình và trình quay trang web

Đây là một lần nữa, trong một vấn đề quan điểm. Có một số vấn đề bạn có thể thấy khi lựa chọn nút Đi tới Thư tiếp theo và những vấn đề này có thể khiến việc loại bỏ hoàn toàn hoặc thay đổi vị trí của nó trong DOM đáng được xem xét.

Vấn đề đầu tiên là chúng tôi không có nút Chuyển đến Thư tiếp theo có thể nhìn thấy, có nghĩa là những người sử dụng trình đọc màn hình có thể nhìn thấy có thể bị nhầm lẫn bởi bước này. Tất nhiên, chúng tôi cũng không có tiêu đề trước đó, nhưng điều đó ít có vấn đề hơn vì khi thêm những thứ này vào mà người ta không thể nhìn thấy, tốt nhất là để nó bám sát bối cảnh trực quan nhất có thể. Không quá mất phương hướng để xem hoặc nghe về tiêu đề bên dưới chữ cái bạn đã nhấp vào vì có thể được thông báo là có một nút ở đó để nhấp vào mà không thể nhìn thấy nút như vậy.

Vì ví dụ này có các bảng chú giải thuật ngữ ngắn như vậy, nên có thể có nút Đi tới Chữ cái Tiếp theo ở cuối mỗi phần của điều khoản hoặc bạn có thể quyết định xóa nó hoàn toàn và nhờ mọi người sử dụng rô-to web của trình đọc màn hình của họ để chuyển đến nút tiếp theo, sẽ hoạt động tốt như nhau nếu bạn có ít định nghĩa hoặc nhiều.

Người dùng có thể nhầm lẫn khi đặt nút Đi tới Chữ cái Tiếp theo trước các định nghĩa vì người dùng thực sự mù có thể nghĩ rằng điều đó có nghĩa là không có thuật ngữ nào được định nghĩa cho chữ cái đó.

Cuối cùng, có một hạn chế của nút Đi tới Thư tiếp theo như được trình bày trong rôto:

Hạn chế của việc có nút Đi tới Thư tiếp theo

Khi sử dụng rôto, bạn không được biết ký tự tiếp theo sẽ là gì hoặc thậm chí là ký tự hiện tại là gì.

Cải thiện điều hướng

Có thể có lợi khi nút Bảng chú giải thuật ngữ hiện tại cho biết đó có phải là chữ cái đang được hiển thị hay không, tức là văn bản có nội dung là nút Hiện đang hiển thị chữ cái A trong bảng chú giải thuật ngữ và nút Chuyển đến chữ cái tiếp theo cho biết nút Chuyển đến chữ cái tiếp theo, nút B.

Do đó, nếu bạn đang điều hướng xuống danh sách các nút trong rôto, bạn có hai nơi sẽ dễ dàng đặt ngữ cảnh của bạn.

Tôi sẽ thực hiện những thay đổi đó, có thể thấy ở đây:

 

 

Vì các nút Đi tới Tiếp theo đều nằm trong đánh dấu, nên tùy thuộc vào bất kỳ mã nào bạn đang sử dụng để tạo ra đánh dấu của mình để tạo ra mã đó (cho dù là mẫu, React, Vue hay chỉ làm bằng tay). Thay đổi có liên quan duy nhất là trong switchSelectedLettershàm, được gọi bất cứ khi nào bạn nhấp vào một trong các nút bảng thuật ngữ, như được hiển thị bên dưới:

const switchSelectedLetters = (target) => {
  const selector = "selectedLetter";
  const currentSelectedLetter = document.querySelector(`.${selector}`);
  const currentAria = currentSelectedLetter.getAttribute("aria-label");
  const targetAria = target.getAttribute("aria-label");
  const selectionText = "Current selected, ";
  //use [...selectionText] because we want number of characters, not code units.
  currentSelectedLetter.setAttribute("aria-label", currentAria.substring([...selectionText].length))
  currentSelectedLetter.classList.remove(selector);
  target.setAttribute("aria-label", selectionText + targetAria);
  target.classList.add(selector);
}

Hãy tiếp tục với những thay đổi này và sử dụng lại bảng thuật ngữ. Bạn được thông báo rằng nút thuật ngữ bạn đang truy cập là nút hiện được chọn.

Nút Đi tới Thư tiếp theo mới của chúng tôi

Khi bạn nhấp vào nút Tiếp theo , nút này sẽ trở thành nút hiện được chọn và bạn có thể thấy nút này trong rôto. Hơn nữa, nút Go to Next Letter cũng cho bạn biết chữ cái tiếp theo sẽ là gì.

Màn hình Bảng điều khiển biểu mẫu bảng thuật ngữ cuối cùng, có thể truy cập của chúng tôi

Tôi nghĩ rằng, cuối cùng, việc triển khai này mang lại cho chúng ta một số tính năng hay để tạo ra một bảng thuật ngữ định nghĩa có thể sử dụng và dễ tiếp cận sẽ mang lại lợi ích không chỉ cho những người dùng khiếm thị mà còn cả những người dùng trình duyệt màn hình khác.

Điều chỉnh bảng thuật ngữ có thể truy cập của chúng tôi cho những người dùng gặp khó khăn về tính di động

Cuối cùng, tôi sẽ nhanh chóng chỉ ra cách mọi thứ có thể truy cập được đối với những người dùng khó khăn về tính di động, những người chủ yếu sử dụng bàn phím để điều hướng.

Nút Hiển thị Bảng chú giải thuật ngữ có thể lập tab được và cho biết khi nào nó được lấy tiêu điểm:

Nút Hiển thị Bảng chú giải thuật ngữ khi được gắn thẻ

Nhấp vào nút sẽ mở bảng thuật ngữ:

Mở bảng thuật ngữ bằng phím tabNhấn lại Tab để chọn nút Đóng :

Đóng nút được chọn bằng Tab

Tab tiếp theo chọn một chữ cái:

Nhấn lại tab để chọn chữ cái tiếp theo

Nếu bạn tab, bạn sẽ chuyển đến chữ cái tiếp theo. Sau đó, bạn có thể nhấp vào để xem định nghĩa của chữ cái và nếu bạn nhấn tab sau đó, bạn sẽ ở lại Đóng chữ cái , vì vậy bạn có thể đóng bất kỳ lúc nào khá nhanh. Bạn có thể muốn thêm một trình xử lý cho phím Escape, trong trường hợp này, để cho phép đóng bảng thuật ngữ bằng cách nhấn phím Escape, nhưng hiện tại, nó có thể sử dụng được và tôi nghĩ là có thể hiểu được về mặt logic.

Sự kết luận

Làm cho một thứ gì đó có thể truy cập được không đặc biệt khó, miễn là bạn có thể hình dung ra những vấn đề mà khách hàng của bạn sẽ gặp phải và ghi nhớ những giới hạn và mô hình của thế giới mà các công nghệ hỗ trợ khác nhau phải hoạt động.

 

Nguồn: https://blog.logrocket.com/building-accessible-glossary-vanilla-javascript/

#javascript 

Hong  Nhung

Hong Nhung

1659514461

Xây Dựng Các Giao Diện JavaScript Phong Phú, Có Thể Truy Cập được

Vì vậy, bạn là một người thích JavaScript, người có thể xây dựng khá nhiều thứ - nhưng mọi người có thể sử dụng nó không? Trong bài viết này, chúng ta sẽ xem xét một số cách để tạo giao diện JavaScript phong phú, dễ truy cập. Chúng tôi sẽ minh họa các chiến lược của mình bằng cách xây dựng một câu đố Sudoku đơn giản phù hợp với tất cả mọi người, ngay cả những người bị mù hoặc một phần thị lực.

Lập kế hoạch cho khả năng tiếp cận ngay từ đầu

Việc trang bị thêm khả năng truy cập vào một giao diện có thể khó khăn và tốn thời gian; bạn sẽ luôn nhận được kết quả tốt hơn nếu bạn lập kế hoạch cho khả năng tiếp cận ngay từ đầu. Bạn có thể đã nghe nói về từ viết tắt POUR, đây là một cách tuyệt vời để lập kế hoạch cho khả năng tiếp cận.

POUR là viết tắt của:

  • Perceivable: Tất cả người dùng sẽ có thể cảm nhận được giao diện. Các yếu tố hình ảnh phải có các lựa chọn thay thế văn bản tương đương và cách phối màu phải thân thiện với những người có thị lực kém
  • Có thể hoạt động: Tất cả người dùng sẽ có thể vận hành giao diện. Đảm bảo rằng mọi thứ có thể được vận hành mà không cần chuột và mục tiêu chạm hoặc nhấp đủ lớn cho tất cả người dùng
  • Dễ hiểu: Giao diện phải đơn giản và trực quan nhất có thể
  • Mạnh mẽ: Giao diện phải hoạt động trên nhiều loại trình duyệt hiện tại và công nghệ hỗ trợ. Điều này có thể có nghĩa là chỉ sử dụng những công nghệ được thiết lập tốt hơn là những công nghệ cung cấp các tính năng "mới nhất và tuyệt vời nhất"

Đối với một trò chơi dựa trên lưới như Sudoku, thách thức lớn nhất liên quan đến khả năng tiếp cận là làm cho giao diện dễ hiểu. Sudoku yêu cầu người chơi biết những con số nào được nhập vào mỗi ô của lưới. Để có thể truy cập được, trò chơi Sudoku sẽ cần phải truyền tải thông tin này đến những người dùng có thể không nhìn thấy bảng trò chơi.

Một câu đố Sudoku chín chữ số cổ điển với 81 ô là quá lớn đối với hầu hết mọi người để giải quyết nếu bảng không hiển thị. Vì vậy, quyết định đầu tiên của tôi là đơn giản hóa mọi thứ và thay vào đó tạo một Sudoku bốn chữ số với 16 ô.

Tiếp theo, cần phải có một cách nhất quán để mô tả gameboard - một hệ thống ký hiệu. Bản năng đầu tiên của tôi là sử dụng một hệ tọa độ XY đơn giản, giống như trong cờ vua. Tuy nhiên, một ô Sudoku phức tạp hơn một bàn cờ vua, nó thực sự là một tập hợp các ô nằm trong một ô lưới lớn hơn.

Đây là hệ thống ký hiệu mà tôi đã giải quyết:

Hệ thống ký hiệu cho Sudoku có thể tiếp cận

Hệ thống ký hiệu cho Sudoku có thể truy cập.

Trò chơi bao gồm bốn hình vuông được sắp xếp trong một lưới hai nhân hai.

Các hình vuông ở hàng trên cùng được ký hiệu là hình vuông A và hình vuông B. Các hình vuông ở hàng dưới cùng được ký hiệu là hình vuông C và hình vuông D.

Mỗi ô vuông chứa bốn ô được sắp xếp trong một lưới hai nhân hai. Các ô ở hàng trên cùng của mỗi ô vuông được chỉ định là ô a và ô b. Các ô ở hàng dưới cùng được chỉ định là ô c và ô d.

Ký hiệu này có thể mô tả bất kỳ ô nào trên bàn cờ và truyền tải thông tin vị trí mà người chơi cần để giải câu đố. Vì vậy, nếu chúng ta kết hợp các cơ chế thông báo vị trí hiện tại của người dùng trình đọc màn hình trên bảng và liệt kê các số trong hàng, cột và ô vuông tương ứng, trò chơi sẽ dễ hiểu.

Xây dựng với các nguyên tắc POUR trong tâm trí

Bây giờ đã đến lúc bắt đầu xây dựng, hãy ghi nhớ các nguyên tắc POUR. Một chiến thuật quan trọng trong việc xây dựng các giao diện có thể truy cập là tránh phát minh lại bánh xe. Nếu một điều khiển HTML tiêu chuẩn lâu đời có sẵn để làm điều gì đó, thì hãy sử dụng nó theo đặc điểm kỹ thuật của nó, áp dụng CSS để tạo bất kỳ hiệu ứng hình ảnh mong muốn nào.

Sudoku thu nhỏ này bao gồm 16 ô được sắp xếp theo dạng lưới, mỗi ô có khả năng chứa một số duy nhất. Vì vậy, tôi đã sử dụng 16 <input type="number>phần tử. Các phần tử này được thiết kế theo đúng nghĩa đen cho công việc này, ngoài ra chúng có một readonlythuộc tính để đánh dấu các ô giá trị cố định cần được đưa vào để làm cho Sudoku có thể giải được.

Tôi đã sử dụng <div>các thẻ để nhóm các ô thành hình vuông và Bố cục Lưới CSS để sắp xếp mọi thứ. Sử dụng Bố cục Lưới CSS thay vì HTML <table>cho phép tôi sắp xếp thứ tự các ô trong mã theo hệ thống ký hiệu của tôi (Aa, Ab, Ac, Ad, Ba, Bb, v.v.). Thứ tự tab của trang phối hợp với cấu trúc cơ bản của nó, vì vậy điều này sẽ giúp giữ cho giao diện dễ hiểu khi người dùng bàn phím di chuyển từ trang này <input>sang trang khác bằng phím tab .

<div class="board">
  <div class="square">
    <input type="number" min="0" max="4" length="1" value="">
    <input type="number" min="0" max="4" value="2" readonly>
    <input type="number" min="0" max="4" value="">
    <input type="number" min="0" max="4" value="">
  </div>
  <div class="square">
    <input type="number" min="0" max="4" value="3" readonly>
    <input type="number" min="0" max="4" value="">
    <input type="number" min="0" max="4" value="">
    <input type="number" min="0" max="4" value="1" readonly>
  </div>
  <div class="square">
    <input type="number" min="0" max="4" value="2" readonly>
    <input type="number" min="0" max="4" value="">
    <input type="number" min="0" max="4" value="">
    <input type="number" min="0" max="4" value="4" readonly>
  </div>
  <div class="square">
    <input type="number" min="0" max="4" value="">
    <input type="number" min="0" max="4" value="">
    <input type="number" min="0" max="4" value="1" readonly>
    <input type="number" min="0" max="4" value="">
  </div>
</div>*, *:before, *:after {
  box-sizing: border-box;
}
body {
  font-size: 1.25rem;
  line-height: 1.35;
}
.board {
  width: 40vh;
  max-width: 90vw;
  height: 40vh;
  max-height: 90vw;
  padding: 0;
  border: 2px solid black;
  display: grid;
  grid-template: repeat(2,1fr) / repeat(2,1fr);
}
.square {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  border: 2px solid black;
  display: grid;
  grid-template: repeat(2,1fr) / repeat(2,1fr);
}
.square input {
  display: block;
  color: black;
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  text-align: center;
  font-size: 7vh;
  border: 1px solid black;
  -moz-appearance: textfield;
}
/* Hide HTML5 Up and Down arrows. */
.square input::-webkit-outer-spin-button, .square input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

Lựa chọn màu sắc và kích thước

Một số vấn đề phổ biến mà giao diện web gặp phải liên quan đến khả năng truy cập là văn bản quá nhỏ và màu giao diện người dùng không cung cấp đủ độ tương phản để có thể dễ dàng nhìn thấy.

Về kích thước, một nguyên tắc chung là để văn bản được hiển thị với kích thước phông chữ hiệu quả không nhỏ hơn 16 pixel CSS (khác với pixel thiết bị). Đối với trò chơi Sudoku, tôi đã sử dụng tối thiểu 20 pixel (được chỉ định 1.25rem1rem16 pixel) và cũng tăng tiêu chuẩn line-heightlên 1,35 để giải phóng nhiều thứ hơn một chút và giúp chúng dễ đọc hơn.

Tôi đã chỉ định kích thước tổng thể của bảng điều khiển bằng cách sử dụng vhcác đơn vị ( 1vhlà 1% chiều cao của khung nhìn) để thử và làm cho nó lớn nhất có thể trong khi vẫn hiển thị các điều khiển trò chơi trong cùng một khung nhìn.

Trò chơi chủ yếu sử dụng màu đen và trắng để tối đa hóa độ tương phản. Tuy nhiên, tôi cũng cần hiển thị ô nào ở chế độ chỉ đọc và tôi muốn sử dụng màu sắc để hiển thị vị trí hiện tại của tiêu điểm bàn phím trong trò chơi và (tùy chọn) đánh dấu các ô chính xác và không chính xác.

Điều này dẫn đến một vấn đề phổ biến khác - đối phó với thị lực màu sắc thấp. Có vẻ bản năng sử dụng màu xanh lá cây để làm nổi bật các ô chính xác và màu đỏ để làm nổi bật các ô không chính xác, nhưng màu đỏ và xanh lá cây là một lựa chọn rất tồi đối với phần lớn những người có thị lực màu sắc kém.

Thay vào đó, tôi đã chọn sử dụng màu xanh da trời để chỉ định các ô chính xác, màu tím đỏ để chỉ định các ô không chính xác và màu vàng để đánh dấu vị trí. Các sắc thái màu chính xác đã được chọn từ bảng màu Wong . Đối với các readonlyô chỉ đọc (), tôi đã sử dụng văn bản màu trắng trên nền màu xám đậm. Tất cả các kết hợp màu này cũng cung cấp đủ độ tương phản, như được đo bằng Công cụ kiểm tra độ tương phản WebAIM .

.correct {
  background-color: #56B4E9;
}
.incorrect {
  background-color: #CC79A7;
}
.square input:focus {
  background-color: #F0E442;
}
.square input:read-only {
  background-color: #333;
  color: white;
}

Kết hợp thêm hỗ trợ với WAI-ARIA

Nó có thể chưa hoạt động, nhưng chúng ta hiện có một thứ trông giống như một trò chơi Sudoku thu nhỏ. Sử dụng chuột, chúng ta có thể dễ dàng trỏ và nhấp để nhập số vào mỗi ô của lưới, và nó cũng hoạt động chỉ bằng bàn phím.

Chúng ta vẫn cần có thể nhìn thấy bảng để điều hướng qua nó, điều này không có ích cho những người bị hạn chế hoặc không có tầm nhìn. May mắn thay, Sáng kiến ​​hỗ trợ truy cập web - Ứng dụng Internet phong phú có thể truy cập ( WAI-ARIA ) có thể giúp kết hợp nhiều hỗ trợ hơn.

Thuộc aria-labeltính được sử dụng để thêm văn bản bổ sung vào những thứ như các phần tử biểu mẫu được phần mềm đọc màn hình đọc to khi chúng được người dùng tập trung vào. Tôi đã sử dụng thuộc tính này để thêm ký hiệu vào mỗi ô.

<div class="board">
    <div aria-label="Square A" class="square">
      <input aria-label="Square A, Cell A." type="number" min="0" max="4" length="1" value="">
      <input aria-label="Square A, Cell B. The value of this cell is fixed." type="number" min="0" max="4" value="2" readonly>
      <input aria-label="Square A, Cell C." type="number" min="0" max="4" value="">
      <input aria-label="Square A, Cell D." type="number" min="0" max="4" value="">
    </div>
    ...
</div>

Tôi không bắt buộc phải thêm giá trị của ô vào aria-labelvì giá trị được đọc ra theo mặc định. Nhưng, tôi tình cờ biết rằng một số trình đọc màn hình không thông báo cho người dùng khi một <input>phần tử ở chế độ chỉ đọc, vì vậy tôi đã bao gồm thông tin đó.

Thêm tương tác

Bây giờ là lúc để trò chơi thực sự làm được điều gì đó.

Chúng tôi muốn có thể:

  • Kiểm tra xem gameboard đã hoàn thành đúng chưa
  • Hiển thị toàn bộ giải pháp cho người chơi gặp khó khăn khi hoàn thành câu đố
  • Khởi động lại trò chơi từ đầu
  • Cung cấp cho người chơi tùy chọn đánh dấu ô nào đúng và ô nào không chính xác

Để đạt được những mục tiêu này, chúng ta cần lưu trữ câu trả lời chính xác cho mỗi ô ở đâu đó và thêm các điều khiển bên dưới bảng điều khiển để kích hoạt mỗi hành động.

Có một số cách chúng tôi có thể lưu trữ các câu trả lời chính xác. Tôi đã chọn thêm một datathuộc tính vào mỗi ô, như thế này:

<input aria-label="Square A, Cell A." data-correct="1" type="number" min="0" max="4" length="1" value="">

Các điều khiển trò chơi cần có thể truy cập được, vì vậy tôi sẽ áp dụng các nguyên tắc thiết kế tương tự như trước đây và sử dụng HTML cổ phiếu ở dạng <button><input type="checkbox">các phần tử.

Mỗi phần tử cần một cái duy nhất idđể tôi có thể gắn các trình nghe sự kiện vào phần tử. Tôi sẽ sử dụng <label>phần tử tiêu chuẩn để đảm bảo rằng hộp kiểm chuyển đổi đánh dấu có thể truy cập được. Tôi cũng sẽ thêm một ô trống <div>mà tôi có thể sử dụng để hiển thị thông báo cho người chơi.

<div class="controls">
    <label><input id="highlight" type="checkbox">&nbsp;HIGHLIGHT</label>
    <button id="check">CHECK YOUR ANSWER</button>
    <button id="show">SHOW SOLUTION</button>
    <button id="restart">RESTART</button>
</div>
<div id="announcement-all-users"></div>

Bốn hàm JavaScript đơn giản là tất cả những gì cần thiết để làm cho trò chơi hoạt động ở mức cơ bản:

let lang = "en";
const messages = {
  en: {
    boardCorrect: "Congratulations, you completed the Sudoku correctly!",
    boardIncorrect: "Hmmm... Not quite correct! Try again. Check 'HIGHLIGHT' to see where you went wrong."
  },
  announcementAllUsersDisplayed: false
}

function highlightCells(e){
  document.querySelectorAll('.square input:read-write').forEach( (cell) => { // toggle correct and incorrect classes for each non read-only cell
    if(document.querySelector('#highlight').checked){
      if(cell.value === cell.dataset.correct){
        cell.classList.add("correct");
        cell.classList.remove("incorrect");
      } else {
        cell.classList.add("incorrect");
        cell.classList.remove("correct");
      }
    } else {
      cell.classList.remove("correct","incorrect");
    }  
  } );
}
document.querySelector('#highlight').addEventListener('change', highlightCells );

function checkAnswer(e) {
  let allCorrect = true;
  document.querySelectorAll('.square input').forEach( (cell) => { // check each cell to see if it is correct
    if( cell.value !== cell.dataset.correct){
      allCorrect = false;
    }  
  } );
  // make general announcement of success/failure
  if(allCorrect){ 
    document.querySelector('#announcement-all-users').innerHTML = messages[lang].boardCorrect;
  } else {
    document.querySelector('#announcement-all-users').innerHTML = messages[lang].boardIncorrect;    
  }
  messages.announcementAllUsersDisplayed = true;  
}
document.querySelector('#check').addEventListener('click', checkAnswer );

function showSolution(e){
  if(messages.announcementAllUsersDisplayed){// remove any existing general annoucements
    document.querySelector('#announcement-all-users').innerHTML = "";
    messages.announcementAllUsersDisplayed = false;
  }
  document.querySelectorAll('.square input').forEach( (cell) => { // set the value of each cell to the correct value
    cell.value = cell.dataset.correct;
  } );  
}
document.querySelector('#show').addEventListener('click', showSolution );

function restartGame(e){
  if(messages.announcementAllUsersDisplayed){ // remove any existing general annoucements
    document.querySelector('#announcement-all-users').innerHTML = "";
    messages.announcementAllUsersDisplayed = false;
  }
  document.querySelectorAll('.square input:read-write').forEach( (cell) => { // reset each non read-only cell to be empty
    if(!cell.classList.contains("readonly")){
      cell.value = "";
    }
  } );  
}
document.querySelector('#restart').addEventListener('click', restartGame );

Hiện chúng tôi có một trò chơi Sudoku đang hoạt động, có thể hiểu được, có thể hoạt động và mạnh mẽ ( hãy kiểm tra trên CodePen ), nhưng chúng tôi vẫn còn một chút việc phải làm để làm cho nó hoàn toàn có thể hiểu được.

Ngoài ra, một số bản cập nhật có thể được thực hiện để giúp trò chơi vận hành dễ dàng hơn. Ví dụ, highlightCellschức năng chỉ hoạt động ở mức độ trực quan. Để hữu ích cho người dùng trình đọc màn hình, chúng ta cần mở rộng nó một chút. Mỗi <input>phần tử của gameboard đã có một aria-labelthuộc tính, vì vậy chúng tôi có thể thao tác điều đó để thêm hoặc xóa thông tin chính xác hoặc không chính xác khi hộp kiểm đánh dấu được bật tắt:

let lang = "en";
const messages = {
  en: {
    cellCorrect: "This cell is correct",
    cellIncorrect: "This cell is incorrect",
    boardCorrect: "Congratulations, you completed the Sudoku correctly!",
    boardIncorrect: "Hmmm... Not quite correct! Try again. Check 'HIGHLIGHT' to see where you went wrong."
  },
  announcementAllUsersDisplayed: false
}

function highlightCells(e){
  if(document.querySelector('#highlight').checked){
    document.querySelector('#highlight-help').classList.remove('v-hidden');
  } else {
    document.querySelector('#highlight-help').classList.add('v-hidden');    
  }
  document.querySelectorAll('.square input:read-write').forEach( (cell) => {
    let ariaLabelSplit = cell.ariaLabel.split('.');
    if(document.querySelector('#highlight').checked){
      if(cell.value === cell.dataset.correct){
        cell.classList.add("correct");
        cell.classList.remove("incorrect");
        cell.ariaLabel = ariaLabelSplit[0] + ". " + messages[lang].cellCorrect;
      } else {
        cell.classList.add("incorrect");
        cell.classList.remove("correct");
        cell.ariaLabel = ariaLabelSplit[0] + ". " + messages[lang].cellIncorrect;
      }
    } else {
      cell.classList.remove("correct","incorrect");
      cell.ariaLabel = ariaLabelSplit[0];
    }  
  } );
}
document.querySelector('#highlight').addEventListener('change', highlightCells ); 

Chức năng đánh dấu giờ sẽ hoạt động cho tất cả mọi người chỉ với những điều chỉnh tối thiểu. Mặc dù vậy, một phần lớn của câu đố vẫn còn thiếu (nếu bạn tha thứ cho cách chơi chữ).

Trò chơi Sudoku được giải khi mỗi hàng, cột và ô vuông chứa các số từ một đến bốn chính xác một lần. Vì vậy, người dùng trình đọc màn hình cần một cách nhanh chóng và dễ dàng không trực quan để tìm ra các số nằm trong một hàng, cột hoặc ô vuông cụ thể. Lần đầu tiên trong dự án này, chúng tôi cần xây dựng thêm chức năng vào trò chơi cho riêng nhóm người dùng này.

Tôi quyết định giải quyết vấn đề này bằng cách thêm một 'read'chức năng vào trò chơi, được kích hoạt bằng phím tắt. Đây là nơi aria-livethuộc tính đi vào. Nếu chúng ta thêm thuộc tính này vào một phần tử (ví dụ: đơn giản <div>), thì khi nội dung của phần tử đó thay đổi, phần mềm đọc màn hình sẽ đọc ra.

Chức năng này có thể được sử dụng để thông báo cho người dùng trình đọc màn hình bằng cách thay đổi nội dung của phần tử bằng JavaScript. Chúng tôi sẽ thêm một aria-livethuộc tính vào phần tử thông báo chung hiện có và một thuộc tính khác vào phần tử cho các thông báo dành riêng cho người dùng trình đọc màn hình. Thông báo cuối cùng này có thể được định vị ngoài màn hình trong phiên bản cuối cùng của trò chơi.

<div id="announcement-sr-only" aria-live="polite"></div>
<div id="announcement-all-users" aria-live="polite"></div>

Giá "polite"trị có nghĩa là khi nội dung của phần tử trực tiếp thay đổi, trình đọc màn hình sẽ hoàn thành nội dung hiện đang đọc trước khi đọc thông báo. Điều này hoạt động tốt cho Sudoku, nhưng nếu chúng tôi cần cảnh báo người dùng về điều gì đó gây bức xúc hơn, chúng tôi có thể đặt aria-live="assertive"điều này sẽ dẫn đến thông báo của chúng tôi được đọc ngay lập tức.

Đây là cách chức năng đọc hoạt động cho trò chơi Sudoku của chúng tôi:

  • Trong khi tiêu điểm bàn phím của người dùng nằm ở một trong các ô của trò chơi, họ nhấn R (đọc), theo sau là R (hàng), C (cột) hoặc S (hình vuông)
  • Tóm tắt nội dung của hàng, cột hoặc hình vuông hiện tại được hiển thị trong announcement-sr-onlyphần tử

Các phím tắt có thể hơi giống một bãi mìn với trình đọc màn hình, vì nhiều phím đã được gán các phím tắt và các phép gán đó có thể thay đổi tùy thuộc vào chế độ của trình đọc màn hình. Vì vậy, hãy sử dụng các phím tắt một cách tiết kiệm, chỉ gắn trình nghe vào các phần tử cần thiết và thực hiện nhiều thử nghiệm!

Để cho phép chức năng đọc hoạt động, tôi đã thêm một idthuộc tính để giúp tôi lặp qua các ô, một data-idphần tử để lặp qua các ô vuông và một lớp bổ sung cho các readonlyô để tôi có thể dễ dàng nhắm mục tiêu các ô đó.

<div class="board">
    <div data-id="A" class="square">
      <input id="11" data-id="A" aria-label="Square A, Cell A." data-correct="1" type="number" min="0" max="4" length="1" value="">
      <input id="12" data-id="B" aria-label="Square A, Cell B. The value of this cell is fixed." data-correct="2" type="number" min="0" max="4" value="2" class="readonly">
      <input id="21" data-id="C" aria-label="Square A, Cell C." data-correct="4" type="number" min="0" max="4" value="">
      <input id="22" data-id="D" aria-label="Square A, Cell D." data-correct="3" type="number" min="0" max="4" value="">
    </div>
    <div data-id="B" class="square">
      <input id="13" data-id="A" aria-label="Square B, Cell A. The value of this cell is fixed." data-correct="3" type="number" min="0" max="4" value="3" class="readonly">
      <input id="14" data-id="B" aria-label="Square B, Cell B." data-correct="4" type="number" min="0" max="4" value="">
      <input id="23" data-id="C" aria-label="Square B, Cell C." data-correct="2" type="number" min="0" max="4" value="">
      <input id="24" data-id="D" aria-label="Square B, Cell D. The value of this cell is fixed." data-correct="1" type="number" min="0" max="4" value="1" class="readonly">
    </div>
    ...
</div>

Đoạn mã dưới đây trình bày cách tôi thiết lập tính tương tác để đọc các hàng. Quá trình đọc các cột và ô vuông tương tự nhau.

const size = 4;
let lang = "en";
const messages = {
  en: {
    cellValue: "The value of this cell is ",
    cellEmpty: "This cell is empty.",
    cellEmptyShort: "Empty",
    cellCorrect: "This cell is correct",
    cellCorrectShort: "correct",
    cellIncorrect: "This cell is incorrect",
    cellIncorrectShort: "incorrect",
    cellFixedShort: "fixed value",
    boardCorrect: "Congratulations, you completed the Sudoku correctly!",
    boardIncorrect: "Hmmm... Not quite correct! Try again. Check 'HIGHLIGHT' to see where you went wrong.",
    reading: "Reading",
    currentRow: "current row",
    currentColumn: "current column",
    currentSquare: "square"
  },
  announcementScreenreaderOnlyDisplayed: false,
  announcementAllUsersDisplayed: false
}

let keyboardNavCapture = 0;
let capturedKeys = "";

document.querySelector('.board').addEventListener('keydown', (e) => { // The keyboard focus needs to be within the gameboard for the shortcut to function 
  if (e.defaultPrevented) {
    return; // Do nothing if the event was already processed. This helps avoids interfering with existing screen reader keyboard shortcuts
  }
  if(e.key === "Escape"){ // allow the user to cancel a partially captured action
    keyboardNavCapture = 0;
    capturedKeys = "";
  } else if(keyboardNavCapture === 0){    
    if(e.key === "r" || e.key === "R"){ // READ action. Capture the next key press to determine what to read
      keyboardNavCapture = 1;
      capturedKeys = "R";
      e.preventDefault();
    }
  } else {
    capturedKeys += e.key.toUpperCase();
    keyboardNavCapture = keyboardNavCapture - 1;
    e.preventDefault();
    if(keyboardNavCapture == 0){
      let actionType = capturedKeys[0];
      let actionDetails = capturedKeys.substring(1); 
      capturedKeys = "";
      if(actionType === "R"){ // READ action
        let activeCellId = parseInt(document.activeElement.id);
        if( (actionDetails === "R" || actionDetails === "C" || actionDetails === "S") && !Number.isNaN(activeCellId) ){
          let row = parseInt(document.activeElement.id[0]) * 10;
          let column = parseInt(document.activeElement.id[1]);
          let cellValue = "";
          let announcementScreenreaderOnly = messages[lang].reading + " ";
          switch (actionDetails){
            case "R": // Read out the current row
              announcementScreenreaderOnly += messages[lang].currentRow + ":";
              for (let col = 1; col < (size + 1); col++) {
                cellValue = document.getElementById("" + (row + col)).value;
                if(cellValue === ""){
                  cellValue = messages[lang].cellEmptyShort;
                } else if(document.getElementById("" + (row + col)).classList.contains('readonly')){
                  cellValue += " (" + messages[lang].cellFixedShort + ")";
                } else if(document.querySelector('#highlight').checked){
                  if(cellValue === document.getElementById("" + (row + col)).dataset.correct){
                    cellValue += " (" + messages[lang].cellCorrectShort + ")";  
                  } else {
                    cellValue += " (" + messages[lang].cellIncorrectShort + ")";
                  }                  
                }
                announcementScreenreaderOnly += " " + cellValue;
                if(col < size){
                  announcementScreenreaderOnly += ",";
                }
              }
              break;
              // switch statement continues for reading columns C and squares S
          }
          document.querySelector("#announcement-sr-only").innerText = announcementScreenreaderOnly;
        }
      }
    }
  }

});

Sau khi xây dựng các kiến ​​thức cơ bản về điều hướng bàn phím, tôi cũng đã thêm các phím tắt cho từng điều khiển trò chơi. Chúng được kích hoạt bởi phím C theo sau là một ký tự đại diện cho điều khiển. Ví dụ: CR khởi động lại trò chơi và CS tiết lộ giải pháp.

Tôi cũng đã thêm "tôi đang ở đâu?" chức năng (được kích hoạt bởi phím W ) và chức năng “đi” (được kích hoạt bởi phím G , theo sau là ký hiệu cho một ô cụ thể) để cho phép di chuyển nhanh chóng xung quanh bảng trò chơi. Bạn có thể xem những điều này được triển khai như thế nào trong CodePen cuối cùng .

Kiểm tra, kiểm tra, kiểm tra!

Về mặt lý thuyết, bây giờ chúng ta sẽ có một câu đố Sudoku hoàn toàn có thể truy cập được! Tuy nhiên, thực tế và lý thuyết không phải lúc nào cũng khớp nhau, vì vậy điều quan trọng là phải kiểm tra trò chơi theo một số cách.

Khi thử nghiệm đầu tiên, hãy luôn kiểm tra xem giao diện có thể hoạt động hoàn toàn mà không cần chuột hay không. Trò chơi của chúng tôi vượt qua điều này với màu sắc bay! Chúng ta có thể sử dụng phím tab hoặc phím tắt để di chuyển xung quanh lưới và các điều khiển trò chơi cũng có thể được kích hoạt bằng bàn phím.

NB , bất kỳ phiên bản cuối cùng nào của trò chơi sẽ cần có đủ tài liệu để thông báo cho người dùng về bất kỳ phím tắt nào

Với thử nghiệm cơ bản chỉ dành cho bàn phím đã vượt qua, đã đến lúc chuyển sang thử nghiệm với trình đọc màn hình.

NVDA trên PC chạy Windows là một lựa chọn chắc chắn để thử nghiệm dành cho nhà phát triển và hoàn toàn miễn phí. Bạn cũng nên sử dụng JAWS nếu bạn có đủ tiền để truy cập một bản sao. Tổng quan của WebAIM bao gồm những điều cơ bản cần thiết để sử dụng NVDA để kiểm tra. Nếu bạn đang sử dụng máy Mac và có sẵn trình đọc màn hình VoiceOver, WebAIM có phần giới thiệu tuyệt vời về việc sử dụng VoiceOver để đánh giá Khả năng truy cập web .

NB , sử dụng trình đọc màn hình trên CodePen khá phức tạp; bạn sẽ nhận được kết quả tốt hơn khi xuất mã và đặt nó trên máy chủ của riêng bạn để thử nghiệm

Tôi đã thử nghiệm trò chơi Sudoku bằng NVDA và hầu hết mọi thứ đều hoạt động tốt. Tuy nhiên, có một mục bất ngờ. Nó chỉ ra rằng khi NVDA vào một readonlyô, nó sẽ chuyển ra khỏi 'focus'chế độ và trở lại 'browse'chế độ. Việc chuyển đổi chế độ này sẽ giết chết các phím tắt, làm cho trò chơi trở nên vô cùng nhạy cảm khi sử dụng. Mặc dù phát hiện ra lỗi này là khó chịu, nhưng nó rõ ràng cho thấy sự cần thiết phải kiểm tra.

Thay vào đó, tôi đã thử sử dụng disabledthuộc tính này một thời gian ngắn, nhưng NVDA thậm chí sẽ không đặt tiêu điểm bàn phím vào các ô bị vô hiệu hóa để điều đó không hoạt động. Thay vào đó, tôi làm lại mã để loại bỏ hoàn toàn các readonlythuộc tính và sau đó tôi sử dụng JavaScript để thực thi hành vi chỉ đọc trên các ô đó.

Trong một thế giới lý tưởng, trò chơi Sudoku của chúng tôi giờ đây sẽ được thử nghiệm trên các trình đọc màn hình khác và phản hồi sẽ được thu thập từ những người dùng thực. Bạn nên luôn đưa bước cuối cùng này vào quy trình phát triển của mình bất cứ khi nào có thể.

Sự kết luận

Mọi thứ trên web đều có thể truy cập được. Bằng cách lập kế hoạch cho khả năng truy cập ngay từ đầu và tuân theo các nguyên tắc POUR trong suốt quá trình thiết kế và xây dựng của bạn, bạn có thể tạo các giao diện JavaScript phong phú mà mọi người đều có thể sử dụng.

Kiểm tra mã cuối cùng cho chính bạn trên CodePen hoặc trên trang độc lập này (để kiểm tra trình đọc màn hình). Tôi cũng đã bao gồm một số điều khiển bổ sung để bạn có thể tự mô phỏng đầu ra của trình đọc màn hình mà không cần sử dụng NVDA và có được ý tưởng về cách trò chơi có thể hoạt động nếu bạn bị mất thị lực một phần hoặc toàn bộ. Cho tôi biết bạn nghĩ gì!

Nguồn: https://blog.logrocket.com/build-rich-accessible-javascript-interfaces/

#javascript 

Hoang  Ha

Hoang Ha

1658558415

Xây Dựng Các Tab Giao Diện Người Dùng Có Thể Truy Cập Trong JavaScript

Các tab giao diện là một thành phần phổ biến của trang web, nhưng các nhà phát triển thường phải đối mặt với những thách thức trong việc làm cho mẫu này có thể truy cập được. Người dùng trình đọc màn hình có thể gặp một số vấn đề khi đọc nội dung và người dùng dựa vào bàn phím để điều hướng qua một trang web có thể yêu cầu một số trợ giúp để điều hướng dễ dàng hơn.

Bài viết này sẽ trình bày mọi thứ bạn cần biết để tạo giao diện tab có thể truy cập, bao gồm xây dựng cấu trúc HTML, thêm kiểu CSS và thêm các cải tiến chức năng JavaScript.

Đây là giao diện theo thẻ mà chúng tôi sẽ xây dựng trong hướng dẫn này:

Giao diện theo tab đã hoàn thành

Một giao diện tab liệt kê các quốc gia khác nhau. Ở bên trái, các tab được hiển thị theo chiều dọc và ở bên phải, có một số văn bản giả và hình ảnh cho quốc gia đã chọn (trong trường hợp này là Mông Cổ).

Bắt đầu nào!

Thiết lập cấu trúc HTML

Cấu trúc HTML rất quan trọng vì nó cung cấp cho người dùng trình đọc màn hình ngữ cảnh cần thiết để điều hướng giao diện.

Có hai cách mà chúng ta có thể sử dụng cấu trúc HTML để giúp xác định những phần tử nào có thể được tập trung vào bằng bàn phím. Chúng tôi có thể sử dụng cách tiếp cận dựa trên liên kết với <a>phần tử làm trình kích hoạt tab của chúng tôi hoặc chúng tôi có thể sử dụng <button>phần tử.

Cả hai cách tiếp cận đều xem xét điều hướng bàn phím bởi bàn phím nguyên bản có thể lấy nét, nhưng mỗi cách đều có ưu và nhược điểm. Chúng tôi sẽ đề cập đến cả hai cách tiếp cận trong bài viết này.

Sử dụng <a>phần tử làm tab

Ưu điểm chính của phương pháp này là chúng ta có thể sử dụng <a>chức năng của phần tử để tạo hiệu ứng điều hướng của tab chỉ bằng HTML và CSS. Yếu <a>tố mang lại sự hỗ trợ bàn phím bằng cách chăm sóc rất nhiều việc quản lý tiêu điểm và điều hướng cho người dùng trình đọc màn hình cho chúng tôi!

Cách tiếp cận này cũng hữu ích cho những người dùng đã tắt JavaScript. Chúng tôi sẽ chỉ sử dụng JavaScript ở cuối hướng dẫn này - để nâng cao một số <a>chức năng của phần tử cho các mục đích trợ năng.

Tuy nhiên, một nhược điểm nhỏ khi sử dụng <a>phần tử làm tab là nó được tính vào lịch sử điều hướng của người dùng. Nói cách khác, nếu người dùng truy cập tất cả các tab và sau đó muốn quay lại trang web trước đó của họ, họ sẽ phải nhấn nút quay lại nhiều lần.

Tuy nhiên, cách tiếp cận này vẫn có những cải tiến liên tục vì nó cung cấp chức năng giao diện tab tốt nhất với công nghệ thấp nhất có thể. Cách tiếp cận này sẽ hoạt động ngay cả khi JavaScript không tải và ngay cả khi CSS cũng không tải được, vì vậy nó đáng xem xét.

Sử dụng <button>phần tử làm tab

Sử dụng <button>phần tử làm tab có ưu điểm là không ảnh hưởng đến lịch sử điều hướng, giúp người dùng quay lại trang web trước đó của họ dễ dàng hơn.

Tuy nhiên, cách tiếp cận này yêu cầu một số cân nhắc bổ sung với HTML để ẩn tất cả nội dung tab không hoạt động. Nó cũng yêu cầu một số quyết định bổ sung liên quan đến JavaScript, chẳng hạn như xác định cách hiển thị nội dung, chiến lược quản lý tập trung và một số cải tiến về khả năng truy cập.

Nếu sử dụng phương pháp này, bạn sẽ cần xem xét điều gì sẽ xảy ra nếu JavaScript không tải trên trang web của bạn. Nếu không có dự phòng, người dùng sẽ không thể điều hướng giao diện theo thẻ của bạn. Có một số lý do khiến JavaScript có thể không tải được. Ví dụ: người dùng có thể bị vô hiệu hóa JavaScript do lo ngại về quyền riêng tư và theo dõi, hoặc JavaScript có thể không tải được do các yếu tố bên ngoài.

Tạo cấu trúc tab giao diện

Sau khi quyết định bạn sẽ sử dụng cách tiếp cận nào, đã đến lúc bắt đầu tạo cấu trúc HTML!

Cấu trúc giao diện tab với <a>cách tiếp cận phần tử

Hãy bắt đầu với các tab riêng lẻ. Ở đây, chúng tôi sẽ sử dụng <a>cách tiếp cận phần tử cho cấu trúc HTML:

<!-- Tab semantics -->
<ul role="tablist">
  <li role="presentation">
    <a role="tab" href="#panel1" id="tab1">Tab one</a>
  </li>
  <li role="presentation">
    <a role="tab" href="#panel2" id="tab2">Tab two</a>
  </li>
  <li role="presentation">
    <a role="tab" href="#panel3" id="tab3">Tab three</a>
  </li>
  <li role="presentation">
    <a role="tab" href="#panel4" id="tab4">Tab four</a>
  </li>
</ul>

<!-- Tab content semantics -->
<div class="tabpanel-container">
  <section role="tabpanel" id="panel1" aria-labelledby="tab1" tabindex="0"></section>
  <section role="tabpanel" id="panel2" aria-labelledby="tab2" tabindex="0"></section>
  <section role="tabpanel" id="panel3" aria-labelledby="tab3" tabindex="0"></section>
  <section role="tabpanel" id="panel4" aria-labelledby="tab4" tabindex="0"></section>
</div>

Bây giờ, hãy kiểm tra cấu trúc được hiển thị trong đoạn mã trên:

  • Vào cuối ngày, danh sách tab chỉ là danh sách các liên kết (hoặc nút) sẽ dẫn chúng ta đến nội dung của chúng ta, vì vậy ngữ nghĩa chính xác cho danh sách tab là bao bọc nó bằng phần tử đã chọn của chúng ta ( <a>hoặc <button>) trong danh sách các mục bên trong một <ul>phần tử
  • Chúng tôi bổ sung tablistvai trò của <ul>mình để cung cấp thêm ngữ cảnh cho người dùng trình đọc màn hình; vai trò này được sử dụng để đánh dấu một vùng chứa bao bọc một tập hợp các tab. Vì tablistvai trò không cung cấp ngữ nghĩa tab cho phần tử con, chúng tôi thêm tabvai trò vào <a>phần tử của chúng tôi
  • Nếu người dùng trình đọc màn hình không đọc được các vai trò tablisttab, HTML sẽ vẫn được đọc dưới dạng danh sách các liên kết hoặc nút, đây là một dự phòng có thể chấp nhận được
  • Chúng tôi thêm presentationvai trò cho các <li>phần tử chỉ để loại bỏ ngữ nghĩa; điều này sẽ giúp ngăn chặn bất kỳ tương tác kỳ lạ nào, trong khi vẫn duy trì dự phòng của chúng tôi trong trường hợp một trình đọc màn hình cụ thể không hỗ trợ vai trò ARIA
  • Nội dung tab của chúng tôi sẽ được đại diện bởi một <section>phần tử có tabpanelvai trò. Phần tử này dự kiến ​​sẽ sử dụng cùng tên của tab với tên có thể truy cập. Đây là lý do tại sao chúng tôi thêm idthuộc tính vào các tab của mình và tại sao chúng tôi sử dụng thuộc tính này làm nhãn trong bảng tab của mình với aria-labelledbythuộc tính
  • Chúng tôi thêm thuộc tính tabindex="0"vào bảng tab của mình để cho phép các mục bên trong tab (như trường biểu mẫu, liên kết hoặc nút) nhận được tiêu điểm bàn phím. Điều này sẽ giúp người dùng bàn phím truy cập nội dung dễ dàng hơn

Cấu trúc giao diện tab với <button>cách tiếp cận phần tử

Nếu chúng tôi sử dụng <button>phương pháp dựa trên cơ sở, chúng tôi sẽ cần bao gồm một bước bổ sung. Chúng tôi sẽ cần thêm hiddenthuộc tính vào tất cả các bảng tab ngoại trừ tab đầu tiên. Thuộc tính này sẽ ẩn các phần tử cho cả người dùng bị cận và người dùng trình đọc màn hình. Để đảm bảo tab đầu tiên vẫn hiển thị, nó phải có aria-selected="true"thuộc tính.

Đánh dấu của chúng tôi cho <button>cách tiếp cận sẽ trông giống như sau:

<!-- Tab semantics -->
<ul role="tablist">
  <li role="presentation">
    <button role="tab" href="#panel1" id="tab1" aria-selected="true">Tab one</button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel2" id="tab2">Tab two</button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel3" id="tab3">Tab three</button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel4" id="tab4">Tab four</button>
  </li>
</ul>

<!-- Tab content semantics -->
<div class="tabpanel-container">
  <section role="tabpanel" id="panel1" aria-labelledby="tab1" tabindex="0"></section>
  <section role="tabpanel" id="panel2" aria-labelledby="tab2" tabindex="0" hidden></section>
  <section role="tabpanel" id="panel3" aria-labelledby="tab3" tabindex="0" hidden></section>
  <section role="tabpanel" id="panel4" aria-labelledby="tab4" tabindex="0" hidden></section>
</div>

Cân nhắc cấu trúc HTML bổ sung

Cho đến nay, chúng tôi đã đề cập đến những cân nhắc ban đầu cho việc đánh dấu của mình, nhưng có những yếu tố bổ sung mà chúng tôi cần lưu ý đối với một số trường hợp sử dụng nhất định. Một số yếu tố sẽ được kiểm soát linh hoạt hơn, nhưng chúng tôi sẽ đề cập đến những yếu tố đó một chút sau trong phần JavaScript của bài viết này.

Liên quan các tab với bảng tab

Chúng tôi có thể liên kết các tab với bảng tab cho người dùng trình đọc màn hình bằng cách sử dụng thuộc tính aria-controls. Tuy nhiên, cách tiếp cận này sẽ chỉ hoạt động trên trình đọc màn hình JAWS và việc sử dụng nó có thể cảm thấy khá dài dòng, như được giải thích trong bài viết của Heydon Pickering . Thay vào đó, chúng tôi sẽ sử dụng một số chiến lược quản lý tiêu điểm cũng sẽ giúp ích cho người dùng bàn phím.

Xử lý các tab dọc

Để hiển thị danh sách tab theo hướng dọc, bạn cần thêm thuộc tính [aria-orientation="vertical"]vào vùng chứa. Điều này sẽ cho người dùng trình đọc màn hình biết rằng các tab được xếp chồng lên nhau theo chiều dọc.

Điều này sẽ quan trọng khi chúng ta bắt đầu thảo luận về các chiến lược điều hướng cho giao diện tab mẫu của chúng ta.

Dưới đây là một ví dụ cho thấy cách [aria-orientation="vertical"]thuộc tính sẽ được sử dụng trong một đoạn mã:

<ul role="tablist" aria-orientation="vertical">
  <li role="presentation">
    <button role="tab" href="#panel1" id="tab1" aria-selected="true">Tab one</button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel2" id="tab2">Tab two</button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel3" id="tab3">Tab three</button>
  </li>
  <li role="presentation">
    <button role="tab" href="#panel4" id="tab4">Tab four</button>
  </li>
</ul>

Chỉ định lựa chọn tab

Khi người dùng nhấp vào một tab, chúng tôi sẽ cần một cách để cho biết rằng tab đó đã được chọn.

Chúng tôi sẽ sử dụng thuộc tính [aria-selected="true"]để chỉ ra lựa chọn tab cho người dùng trình đọc màn hình. Sau đó, chúng tôi sẽ tạo kiểu cho nó bằng CSS để giúp chỉ ra lựa chọn cho những người dùng bị khiếm thị. Thuộc [aria-selected="true"]tính sẽ thay đổi động với JavaScript, vì vậy nó sẽ không được thêm vào đánh dấu ban đầu của chúng tôi.

<li role="presentation">
  <button role="tab" href="#panel1" id="tab1" aria-selected="true">Tab one</button>
</li>

Bây giờ chúng ta đã có một cấu trúc HTML vững chắc, đã đến lúc thêm một số kiểu với CSS !

Thêm kiểu dáng và bố cục bằng CSS

Đối với giao diện tab ví dụ của chúng tôi, chúng tôi đang sử dụng cách tiếp cận dựa trên liên kết với <a>phần tử làm trình kích hoạt tab của chúng tôi. Để tạo kiểu cho cấu trúc tab HTML, chúng ta sẽ cần thêm điều hướng tab, tạo chỉ báo tiêu điểm và xác định kiểu của trạng thái đã chọn.

Thêm điều hướng tab

Để thêm điều hướng tab, hãy thêm quy tắc CSS bằng cách sử dụng :targetbộ chọn như sau:

.tabpanel:not(:target):not(.visible) {
  display: none;
}

:targetlà một lớp giả để kiểm tra xem một phần tử có một phần tử có idkhớp với phân đoạn của URL hay không.

Vì chúng tôi đang sử dụng <a>phần tử ở đây để thêm chức năng, chúng tôi có thể sử dụng bộ chọn này để ẩn bất kỳ bảng tab nào không hoạt động. Chúng tôi đang sử dụng visiblelớp như một ngoại lệ trong ví dụ của mình để chúng tôi có thể thêm một số cải tiến với JavaScript sau này .

Tạo chỉ báo tiêu điểm

Một điều khác chúng ta cần lưu ý là điều hướng bàn phím và một trong những điều quan trọng nhất cần làm về vấn đề đó là tạo ra một chỉ báo lấy nét phù hợp.

Bạn có thể đã nhận thấy một chỉ báo tiêu điểm trong khi điều hướng một trang web bằng phím tab . Tùy thuộc vào trình duyệt của bạn, sẽ xuất hiện dưới dạng đường viền màu xanh lam hoặc đen làm nổi bật một phần tử đã chọn.

Các trình duyệt cung cấp các kiểu tiêu điểm mặc định, nhưng chúng không đủ để đáp ứng tiêu chí WCAG 2.2 . Do đó, cần phải sử dụng thêm kiểu dáng. Để biết thêm thông tin chuyên sâu về cách tạo chỉ báo tiêu điểm tốt, hãy đọc bài viết của Sara Souiedan về chủ đề này.

Đối với ví dụ của chúng tôi, chúng tôi sẽ sử dụng các kiểu tiêu điểm sau:

.tab:focus-visible {
  background-color: royalblue;
  color: whitesmoke;
  outline: 0.2em solid transparent;
}

Tôi quyết định sử dụng :focus-visiblethay vì lớp :focusgiả để kích hoạt kiểu tiêu điểm chỉ với điều hướng bàn phím. Lớp :focusgiả cũng sẽ kích hoạt khi phần tử được nhấp vào, điều này có thể gây nhầm lẫn cho người dùng.

:focus-visibleđược hỗ trợ rất tốt trong các trình duyệt hiện đại, vì vậy nó sẽ không tạo ra bất kỳ loại xung đột nào. Để biết thêm thông tin về thuộc tính này, hãy tham khảo tài liệu MDN .

Tùy chọn “Mông Cổ” được chọn bên dưới cho biết trạng thái tiêu điểm của tab của chúng tôi sẽ trông như thế nào:

Tab Mông Cổ

Tab đầu tiên trong danh sách tab dự án có nền màu xanh lam, cung cấp manh mối trực quan để chọn tab cho người dùng bàn phím.

Đối với dự án này, tôi quyết định sử dụng một phác thảo minh bạch. Điều này rất quan trọng đối với chế độ tương phản cao của Windows . Trong chế độ này, tất cả văn bản và màu nền được thay thế bằng những màu do hệ điều hành chọn, vì vậy chúng tôi không thể phụ thuộc vào màu nền để biểu thị trạng thái tiêu điểm. Phác thảo là cách đáng tin cậy duy nhất để chỉ ra trạng thái tiêu điểm.

Xác định kiểu của trạng thái đã chọn

Bây giờ, hãy quay lại những gì tôi đã đề cập trước đó về việc sử dụng aria-selected="true"thuộc tính để giúp người dùng trình đọc màn hình dễ dàng xác định tab đã chọn hơn. Chúng tôi cũng có thể sử dụng bộ chọn này để cung cấp gợi ý trực quan cho tab đã chọn!

.tab[aria-selected="true"] {
  background-color: var(--component-bg);
}

Cách tiếp cận này tạo ra một vấn đề nhỏ do tính đặc hiệu của CSS hoạt động như thế nào. Cả hai bộ chọn .tab:focus-visible.tab[aria-selected="true"]đều có cùng mức độ cụ thể và cả hai đều thay đổi thuộc background-colortính, do đó, thứ tự quy tắc bộ chọn là rất quan trọng.

Chúng tôi muốn trạng thái tiêu điểm background-colorghi đè bất kỳ trạng thái nào khác background-color, bao gồm cả trạng thái của trạng thái đã chọn, vì vậy chúng tôi sẽ thêm .tab:focus-visiblequy tắc bộ chọn sau quy tắc .tab[aria-selected="true"]bộ chọn.

Đây là kết quả của chúng tôi; lưu ý cách cả hai kiểu tương tác với nhau mà không có bất kỳ vấn đề cụ thể nào:

Tab Myanmar

Tab đầu tiên trong danh sách tab dự án được kích hoạt và có nền màu xám, trong khi tab thứ ba đang được lấy nét bằng bàn phím và có nền màu xanh lam.

Nếu bạn đang sử dụng <a>phần tử làm tab của mình, bạn đã tạo một giao diện tab chức năng với công nghệ thấp nhất có thể!

Nếu bạn đã sử dụng <button>phương pháp dựa trên cơ sở, đừng lo lắng! Tiếp theo, chúng tôi sẽ thêm một số chức năng với JavaScript, điều này sẽ rất quan trọng để làm cho giao diện theo thẻ dễ tiếp cận hơn.

Thêm các cải tiến và chức năng với JavaScript

Có rất nhiều thứ để giải nén trong phần này; hãy bắt đầu bằng cách xem Hướng dẫn Thực hành Tác giả ARIA (APG) nói gì về mẫu thành phần này. Đây là những gì mà hướng dẫn mẫu của ARIA APG cho giao diện tab coi là quan trọng đối với phím tab , các phần tử tabindextrong tabpanelvà các phím mũi tên .

Quản lý phím tab

Về việc sử dụng phím tab , ARIA APG đề xuất những điều sau :

Khi tiêu điểm di chuyển vào danh sách tab, hãy đặt tiêu điểm vào tabphần tử hiện hoạt.

Nhiệm vụ đầu tiên của chúng ta là xóa điều hướng bàn phím bằng phím tab sang tab không được chọn để khi nhấn phím, tiêu điểm sẽ đi thẳng vào bảng tab đang hoạt động. Sau đó, khi nhấn phím shift + tab từ bảng điều khiển đang hoạt động, tiêu điểm sẽ quay trở lại tab tương ứng. Ngoài ra, chúng tôi sẽ phải chỉ ra lựa chọn tab cho cả người dùng trình đọc màn hình và người dùng bị mờ.

Đây là mã tôi đã sử dụng để giải quyết các tác vụ này:

const TABLIST = document.querySelector("#tablist");
const TABS = [...TABLIST.querySelectorAll(".tab")];

const setSelectedTab = (element) => {
  const selectedId = element.id;

  TABS.forEach((e) => {
    const id = e.getAttribute("id");
    if (id === selectedId) {
      e.removeAttribute("tabindex");
      e.setAttribute("aria-selected", "true");
    } else {
      e.setAttribute("tabindex", "-1");
      e.setAttribute("aria-selected", "false");
    }
  });
};

Ở đây, chúng tôi chọn tất cả các tab và lưu trữ một tab đang được nhấp vào. Sau đó, chúng tôi phân tích cú pháp mảng với tất cả các tab của mình và so sánh từng idthuộc tính để kiểm tra xem đó có phải là tab đã được chọn hay không.

Nếu tab không phải là tab chúng ta muốn chọn, chúng ta sẽ thêm các thuộc tính tabindex="-1"aria-selected="false". Tuy nhiên, nếu tab chúng tôi muốn chọn, chúng tôi xóa tabindexthuộc tính và thêm aria-selected="true"thuộc tính. Các phần tử <a><button>có thể lấy tiêu điểm bàn phím theo mặc định, vì vậy không cần thêm a tabindex="0".

Thuộc tabindex="-1"tính này sẽ làm cho một phần tử không thể lấy tiêu điểm bằng phím tab . Khi phím được nhấn, nó sẽ di chuyển tiêu điểm trực tiếp đến bảng tab đang hoạt động của chúng tôi, cho phép chúng tôi chuyển tất cả các tab của mình. Điều này cũng quan trọng vì nó cũng sẽ cho phép chúng tôi quản lý trọng tâm của các tab trong một tab khác mà tôi sẽ trình bày ở phần sau của bài viết này .

Bây giờ tất cả những gì chúng ta cần làm là thêm trình nghe sự kiện vào các tab của mình để thực thi chức năng này! Đối với cách tiếp cận dựa trên liên kết, chúng tôi sẽ cần thêm một trình xử lý sự kiện bổ sung vào các yếu tố đó.

Với <button>cách tiếp cận dựa trên cơ sở, bất kỳ sự kiện nhấp chuột nào sẽ được kích hoạt bằng phím enter và phím cách . Tuy nhiên, một <a>phần tử sẽ chỉ thêm những sự kiện đó bằng phím enter , vì vậy chúng tôi sẽ cần thêm trình xử lý sự kiện phím xuống để kiểm tra khi nào phím khoảng trắng được nhấn.

const handleClick = () => {
  TABS.forEach((element) => {
    element.addEventListener("click", function () {
      setSelectedTab(element);
    });
  });

  // Activates tab with Space. Only necessary if you use the <a> element as a tab

  TABS.forEach((element) => {
    element.addEventListener("keydown", function (e) {
      if ((e.keyCode || e.which) === 32) {
        setSelectedTab(element);
        element.click();
      }
    });
  });
};

Đây là kết quả của chúng tôi!

Điều hướng tab dọc

Dự án mẫu với điều hướng tab dọc. Khi phím tab được nhấn, nó sẽ di chuyển tiêu điểm bàn phím đến bảng tab; khi nhấn phím shift +, nó sẽ di chuyển tiêu điểm đến tab đã chọn.

Quản lý các yếu tố tabindextrongtabpanel

ARIA APG đề xuất những điều sau cho tương tác bàn phím danh sách tab :

Khi danh sách tab chứa tiêu điểm, [tab] sẽ di chuyển tiêu điểm đến phần tử tiếp theo trong chuỗi tab trang bên ngoài danh sách tab, đó là bảng tab trừ khi phần tử đầu tiên chứa nội dung có ý nghĩa bên trong bảng tab có thể lấy tiêu điểm.

Dựa trên đề xuất này, nhiệm vụ tiếp theo của chúng ta là kiểm tra xem mỗi bảng tab có chứa phần tử có thể lấy tiêu điểm hay không.

Đối với các bảng tab không chứa phần tử có thể lấy tiêu điểm, chúng tôi sẽ giữ lại tabindex="0"thuộc tính mà chúng tôi đã thêm trước đó. Nếu không, chúng tôi sẽ cập nhật thuộc tính thành tabindex="-1", vì vậy khi nhấn phím tab , tiêu điểm sẽ được chuyển đến phần tử có thể lấy tiêu điểm đầu tiên bên trong bảng tab.

Chúng tôi sẽ sử dụng đoạn mã này để kiểm tra xem mọi bảng điều khiển tab có chứa các phần tử có thể tiêu điểm hay không và thay đổi tabindexthuộc tính nếu cần:

const TABPANELS = [...document.querySelectorAll(".tabpanel")];

const determineTabindex = () => {
  TABPANELS.forEach((element) => {
    const focusableElements = element.querySelectorAll(
      'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled]), details:not([disabled]), summary:not(:disabled)'
    ).length;

    focusableElements
      ? element.setAttribute("tabindex", "-1")
      : element.setAttribute("tabindex", "0");
  });
};

Đây là kết quả của chúng tôi!

Điều hướng bàn phím

Giao diện theo thẻ với điều hướng bàn phím. Khi bảng điều khiển tab có phần tử có thể lấy tiêu điểm và chúng tôi điều hướng bằng phím tab, tiêu điểm sẽ được chuyển đến phần tử có thể lấy tiêu điểm đầu tiên. Nếu không, tiêu điểm sẽ nằm trên chính bảng tab.

Trong ví dụ này, khi chúng tôi cố gắng sử dụng bàn phím để điều hướng giao diện, phần tử được tiêu điểm sẽ khác nhau tùy thuộc vào việc bảng tab có chứa phần tử có thể lấy tiêu điểm bằng bàn phím hay không.

Quản lý điều hướng bằng các phím mũi tên

ARIA APG đưa ra các đề xuất điều hướng bàn phím cụ thể tùy thuộc vào hướng của các tab trên giao diện.

Dưới đây là các đề xuất khi tiêu điểm nằm trên một phần tử tab trong danh sách tab ngang :

mũi tên trái : Di ​​chuyển tiêu điểm đến tab trước đó. Nếu tiêu điểm nằm trên tab đầu tiên, hãy chuyển tiêu điểm đến tab cuối cùng. Theo tùy chọn, kích hoạt tab mới được tập trung.
mũi tên phải : Chuyển tiêu điểm sang tab tiếp theo. Nếu tiêu điểm nằm trên phần tử tab cuối cùng, hãy di chuyển tiêu điểm đến tab đầu tiên. Theo tùy chọn, kích hoạt tab mới được tập trung.

Nếu bạn đang xây dựng một giao diện với các tab được hiển thị theo chiều dọc, ngoài việc sử dụng thuộc tính aria-orientation="vertical", bạn sẽ phải sử dụng các phím mũi tên lênxuống thay vì các phím mũi tên trái và mũi tên phải .

Dưới đây là các đề xuất khi danh sách tab có hướng aria được đặt thành vertical :

Khi danh sách tab có hướng aria được đặt thành vertical:
mũi tên xuống hoạt động như mũi tên phải được mô tả ở trên.
mũi tên lên hoạt động như mũi tên trái được mô tả ở trên.

Ý định của tôi cho dự án này là xây dựng một giao diện hoàn toàn linh hoạt, nhưng với cách tiếp cận này vào một thời điểm nào đó, màn hình sẽ trở thành danh sách tab ngang hoặc danh sách tab dọc. Làm thế nào để chúng tôi giải quyết vấn đề này?

Hãy bắt đầu bằng cách xác định những phím mũi tên mà chúng ta nên sử dụng. Trong trường hợp cụ thể này, chúng tôi có hai lựa chọn thay thế:

  1. Kiểm tra chiều rộng và chiều cao của danh sách tab. Nếu chiều cao lớn hơn chiều rộng, hãy thêm thuộc tính aria-orientation="vertical"và chỉ hỗ trợ điều hướng mũi tên lên và mũi tên xuống . Nếu không, hãy thêm thuộc tính aria-orientation="horizontal"và chỉ hỗ trợ điều hướng mũi tên trái và mũi tên phải .
  2. Hỗ trợ cả 4 phím điều hướng cùng lúc. Nếu người dùng nhấn vào mũi tên xuống hoặc mũi tên phải , nó sẽ chuyển tiêu điểm sang tab tiếp theo. Nếu họ nhấn vào mũi tên trái hoặc mũi tên lên , nó sẽ chuyển tiêu điểm đến tab trước đó.

Tôi thường thích giải pháp đơn giản nhất, vì vậy tôi sẽ chọn tùy chọn thứ hai. Tuy nhiên, mỗi dự án là khác nhau. Nếu danh sách tab của bạn luôn ở vị trí thẳng đứng, tốt hơn hết bạn nên sử dụng aria-orientation="vertical"và chỉ hỗ trợ điều hướng mũi tên lên và mũi tên xuống .

Đây là mã tôi đã sử dụng, dựa trên tùy chọn thứ hai:

const createArrowNavigation = () => {
  const firstTab = TABS[0];
  const lastTab = TABS[TABS.length - 1];

  TABS.forEach((element) => {
    element.addEventListener("keydown", function (e) {
      if ((e.keyCode || e.which) === 38 || (e.keyCode || e.which) === 37) {
        if (element == firstTab) {
          e.preventDefault();
          lastTab.focus();
        } else {
          e.preventDefault();
          const focusableElement = TABS.indexOf(element) - 1;
          TABS[focusableElement].focus();
        }
      } else if (
        (e.keyCode || e.which) === 40 ||
        (e.keyCode || e.which) === 39
      ) {
        if (element == lastTab) {
          e.preventDefault();
          firstTab.focus();
        } else {
          e.preventDefault();
          const focusableElement = TABS.indexOf(element) + 1;
          TABS[focusableElement].focus();
        }
      }
    });
  });
};

Trước đây, chúng tôi đã tạo một biến lưu trữ tất cả các tab của chúng tôi. Chúng tôi có thể sử dụng nó để xác định đâu là tab điều hướng đầu tiên và cuối cùng. Điều này rất quan trọng vì các tab này có hành vi đặc biệt.

Tiếp theo, chúng ta có thể kiểm tra mã khóa nào liên quan đến từng phím mũi tên. Đối với điều đó, chúng ta có thể sử dụng trang keycode.info để kiểm tra. Để dễ dàng quá trình này, đây là danh sách các mã khóa:

Chìa khóaMã khóa
Mũi tên trái37
Mũi tên lên38
Mũi tên bên phải39
Mũi tên Xuống40

Bây giờ, chúng ta lắng nghe từng phím để kiểm tra vị trí của tab được tập trung trong mảng và chúng ta tập trung vào phần tử tiếp theo ( mũi tên phải và mũi tên xuống ) hoặc phần tử trước đó ( mũi tên trái và mũi tên lên ) trong mảng với focus()phương thức . . Vì các phần tử này có tabindex="-1"thuộc tính, chúng tôi sẽ có thể tập trung chúng bằng phương pháp này.

Hãy nhớ rằng nếu phần tử là phần tử đầu tiên trên mảng, nó sẽ chuyển tiêu điểm đến phần tử cuối cùng và ngược lại. Một điểm cần lưu ý nữa là các phím mũi tên còn có chức năng di chuyển thanh cuộn; chúng ta có thể ngăn chặn hành vi này bằng e.preventDefault()phương pháp này.

Đây là giao diện của chúng tôi, hiển thị việc sử dụng các phím mũi tên để di chuyển giữa các tab:

Sử dụng phím mũi tên

Giao diện tab với điều hướng bàn phím, sử dụng các phím mũi tên để di chuyển giữa các tab.

Xác định cách hiển thị nội dung

Ngoài việc quản lý trạng thái tập trung của thành phần, chúng ta cần xác định thời gian để kích hoạt tab mới được tập trung. Nói cách khác, khi nào bảng tab sẽ được hiển thị? Nó sẽ được hiển thị khi tab được nhấp hoặc khi tiêu điểm được đưa đến tab đã chọn?

Câu trả lời cho chủ đề này mang nhiều sắc thái đáng ngạc nhiên, và W3C có cả một phần liên quan đến chủ đề này . Tóm lại W3C, việc thay đổi nội dung hiển thị tại thời điểm lấy nét một phần tử (được gọi là tiêu điểm theo dõi) có thể có lợi cho một số thành phần nhất định nhưng lại tạo ra lỗi trợ năng cho những thành phần khác.

Hiển thị nội dung tại thời điểm nhấp chuột

Hiển thị nội dung tại thời điểm lấy nét có thể giúp điều hướng bàn phím dễ dàng hơn cho người dùng có mắt, nhưng người dùng trình đọc màn hình có thể không biết rằng nội dung mới đã được thêm vào trang. Ngoài ra, chúng tôi cần xem xét số lượng nội dung sẽ được hiển thị vì điều này có thể ảnh hưởng đến hiệu suất.

Tôi đề nghị hiển thị nội dung khi tab được nhấp vào. Tùy chọn này có thể yêu cầu thêm một phím bấm cho người dùng bàn phím, nhưng nó sẽ cung cấp trải nghiệm toàn diện hơn cho người dùng trình đọc màn hình.

Khi <a>phần tử được nhấp, tiêu điểm sẽ được đưa đến bảng tab đã chọn, bảng điều khiển này sẽ bao gồm điều hướng cho người dùng trình đọc màn hình.

Hiển thị nội dung tại thời điểm tiêu điểm

Nếu bạn quyết định hiển thị nội dung dựa trên tiêu điểm, hãy đảm bảo sử dụng <button>phương pháp tiếp cận, thay vì <a>phương pháp tiếp cận yếu tố.

Với một <button>phần tử, bạn sẽ cần xử lý việc quản lý tiêu điểm bằng JavaScript. Đối với điều đó, chúng tôi sẽ quay lại handleClickchức năng mà chúng tôi đã tạo trước đó trong phần CSS của bài viết này và chúng tôi sẽ thêm một số điều chỉnh.

Đầu tiên, chúng tôi sẽ tạo một chức năng thêm hoặc xóa thuộc tính hiddentùy thuộc vào việc bảng tab có đang được nhắm mục tiêu hay không. Nếu bảng tab là mục được nhắm mục tiêu, chúng tôi cũng sẽ di chuyển tiêu điểm bàn phím đến nó. Đây là cách tiếp cận của tôi đối với vấn đề này:

const showActivePanel = (element) => {
  const selectedId = element.id;
  TABPANELS.forEach((e) => {
    e.hidden = "true";
  });
  const activePanel = document.querySelector(
    `[aria-labelledby="${selectedId}"]`
  );
  activePanel.removeAttribute("hidden");
        activePanel.focus()
};

Những gì chúng tôi đang làm ở đây là ẩn tất cả các bảng tab bằng cách thêm hiddenthuộc tính vào chúng. Tiếp theo, chúng tôi sẽ chọn bảng điều khiển tab được nhắm mục tiêu của mình bằng cách sử dụng aria-labelledbygiá trị của thuộc tính. Hãy nhớ rằng, mỗi buttoncái có một idcái mà chúng tôi đang sử dụng để gắn nhãn bảng điều khiển tab bằng cách sử dụng thuộc tính này; điều này sẽ giúp chúng tôi chọn đúng bảng tab.

Bây giờ, chúng ta chỉ cần loại bỏ hiddenthuộc tính và sau đó đưa tiêu điểm bàn phím đến nó bằng focus()phương thức. Cuối cùng, chúng tôi thêm showActivePanelchức năng trong chức năng của chúng tôi handleClickđể được thực thi khi nhấp chuột.

Bây giờ là lúc để xem toàn bộ thành phần hoạt động như thế nào!

Nhấp vào Điều hướng

Giao diện theo thẻ hiển thị nội dung khi nhấp chuột; các phím mũi tên được sử dụng để điều hướng bàn phím giữa các tab.

Xử lý <a>trạng thái ban đầu của phần tử

Nếu chúng tôi chọn sử dụng một <a>phần tử cho các tab của mình, chúng tôi sẽ cần xử lý trạng thái ban đầu của phần tử nếu JavaScript đang hoạt động.

Dưới đây là các hành động chúng tôi muốn thực hiện khi tải tài liệu:

  • Nếu URL của trang web không trỏ đến bảng tab, bảng đầu tiên sẽ hiển thị, tab đầu tiên phải có thuộc tính aria-selected="true"và có thể đặt tiêu điểm bằng bàn phím khi nhấn phím tab ; các tab khác nên có aria-selected="false"tabindex="-1"các thuộc tính
  • Nếu URL của trang web trỏ đến một bảng điều khiển, thì bảng điều khiển trong URL này sẽ hiển thị; tab tương ứng phải có các thuộc tính đã đề cập trước đó: aria-selected="true"no tabindex

Chúng tôi sẽ tạo các chức năng cho cả hai trường hợp.

const activateFirstPanel = () => {
  TABS[0].setAttribute("tabindex", "0");
  TABS[0].setAttribute("aria-selected", "true");
  TABPANELS[0].classList.add("visible");
};

Chức năng này sẽ bao gồm trường hợp đầu tiên của chúng tôi. Nó thực sự khá đơn giản. Chúng ta đã có danh sách nút TABSTABPANELS, chúng ta có thể chọn phần tử đầu tiên của mỗi danh sách và thêm các thuộc tính cần thiết.

Trong phần CSS trước đó, tôi đã đề cập rằng chúng tôi đang sử dụng visiblelớp làm ngoại lệ và sẽ thêm một số cải tiến với JavaScript sau. Vâng, bây giờ là thời điểm cho các cải tiến JavaScript!

Chúng tôi thêm lớp này vào bảng tab đầu tiên để hiển thị nó. Khi người dùng bắt đầu tương tác với tab, chúng tôi cần xóa lớp này.

const checkInitialSelectedTab = () => {
  const targetedTabPanel = document
    .querySelector(".tabpanel:target")
    .getAttribute("aria-labelledby");
  const selectedTab = document.querySelector(`#${targetedTabPanel}`);
  selectedTab.setAttribute("aria-selected", "true");
  selectedTab.removeAttribute("tabindex");
};

Kịch bản thứ hai của chúng tôi phức tạp hơn một chút. Vì bảng điều khiển này đang được nhắm mục tiêu, nó sẽ được hiển thị trên màn hình theo mặc định - điều này là do bộ chọn
.tabpanel:not(:target):not(.visible)chúng tôi đã sử dụng trước đây. Tuy nhiên, chúng ta cần tìm tab kích hoạt bảng điều khiển.

Đối với điều này, chúng tôi sẽ chọn bảng điều khiển tab được nhắm mục tiêu bằng JavaScript bằng cách sử dụng .tabpanel:targetbộ chọn trong querySelector()phương pháp. Khi chúng ta có nút đó, chúng ta sẽ nhận được aria-labelledbythuộc tính. Tab idnày giống với tab mà chúng tôi đang sử dụng trong aria-labelledbythuộc tính của bảng điều khiển này, vì vậy chúng tôi sẽ sử dụng tab đó idđể tìm kiếm tab và sau đó chúng tôi sẽ thêm các thuộc tính cần thiết.

Bây giờ, chúng ta chỉ cần thực thi các hàm đó tùy thuộc vào URL chứa gì, vì vậy chúng ta sẽ sử dụng một hàm khác để xử lý điều này:

const handleInitialState = () => {
  TABS.forEach((e) => {
    e.setAttribute("tabindex", "-1");
    e.setAttribute("aria-selected", "false");
  });

  window.location.href.indexOf("#panel") === -1
    ? activateFirstPanel()
    : checkInitialSelectedTab();

  determineTabindex();
};

Vâng, tôi đã nói dối. Chỉ còn một chút công việc nữa mà chúng ta cần làm trong chức năng này.

Đối với người mới bắt đầu, hãy đặt aria-selectedthuộc tính của tất cả các tab thành falsetabindexthuộc tính thành -1; sau đó chúng tôi sẽ sửa lỗi chính xác với các chức năng đã tạo.

Tiếp theo, chúng ta cần kiểm tra xem một bảng tab có đang được nhắm mục tiêu trong URL của trang web hay không. Chúng tôi có thể sử dụng window.location.hrefphương pháp để lấy URL và sau đó sử dụng indexOfphương pháp mảng để kiểm tra xem có bảng điều khiển được nhắm mục tiêu trong URL này hay không.

Khi bạn sử dụng một hàm mảng trong một chuỗi, chẳng hạn như URL của chúng tôi, nó sẽ tạo một mảng với mỗi ký tự trong chuỗi là một phần tử của mảng này, nếu cả thế giới nằm trong URL này, nó sẽ trả về vị trí bắt đầu của chuỗi, nếu không, nó sẽ trả về -1. Đây là những gì chúng tôi sẽ sử dụng để xác định hàm nào sẽ thực thi.

Bây giờ, chúng ta sẽ thực thi determineTabindex()hàm mà chúng ta đã tạo trước đó. Chúng tôi sẽ xóa no-jslớp mà chúng tôi đã thêm trong HTML của mình và được sử dụng để tạo dự phòng trong trường hợp JavaScript không tải.

Chúng tôi sắp hoàn thành!

Trước đây, chúng tôi đã tạo một chức năng để kiểm tra xem các bảng tab có các phần tử có thể lấy tiêu điểm determineTabIndex():; chức năng đó cần được thêm vào đó.

Bạn có nhớ setSelectedTab()chức năng của chúng tôi? Chúng ta cần thêm một dòng nhỏ để xóa visiblelớp trong trường hợp nó đã được sử dụng. Để làm như vậy, chúng tôi sẽ thêm mã TABPANELS[0].classList.remove("visible");trước khi bắt đầu kiểm tra từng tab.

Cuối cùng, hãy sử dụng lệnh sau để đảm bảo chức năng của chúng ta handleInitialState()chạy khi trang web tải:

window.onload = handleInitialState;

Hãy nhớ rằng, phần này chỉ áp dụng nếu bạn đã sử dụng <a>phần tử để xử lý điều hướng của các tab.

Kết thúc

Dưới đây là giao diện tab có thể truy cập hoàn chỉnh của chúng tôi! Sau khi xem xét nhiều lựa chọn, tôi đã sử dụng cách tiếp cận dựa trên liên kết với <a>phần tử cho bản trình diễn này. Giao diện người dùng theo tab được thiết kế với bố cục hoàn toàn linh hoạt mà không cần truy vấn phương tiện.

https://codepen.io/ItsCrisDiaz/pen/LYQjGpW

Thành phần này giải quyết các vấn đề trợ năng chính mà các nhà phát triển gặp phải khi xây dựng giao diện theo thẻ: đảm bảo rằng nó hoạt động bình thường cho người dùng bàn phím và thông tin được hiển thị chính xác cho người dùng trình đọc màn hình.

Việc xây dựng một thành phần có thể truy cập có thể là một thách thức do nhiều sắc thái của các yêu cầu về khả năng truy cập, nhưng điều quan trọng là phải đảm bảo trang web của bạn có thể sử dụng được cho tất cả mọi người.

 Nguồn: https://blog.logrocket.com/build-accessible-user-interface-tabs-javascript/

#javascript 

Rahul Jangid

1622207074

What is JavaScript - Stackfindover - Blog

Who invented JavaScript, how it works, as we have given information about Programming language in our previous article ( What is PHP ), but today we will talk about what is JavaScript, why JavaScript is used The Answers to all such questions and much other information about JavaScript, you are going to get here today. Hope this information will work for you.

Who invented JavaScript?

JavaScript language was invented by Brendan Eich in 1995. JavaScript is inspired by Java Programming Language. The first name of JavaScript was Mocha which was named by Marc Andreessen, Marc Andreessen is the founder of Netscape and in the same year Mocha was renamed LiveScript, and later in December 1995, it was renamed JavaScript which is still in trend.

What is JavaScript?

JavaScript is a client-side scripting language used with HTML (Hypertext Markup Language). JavaScript is an Interpreted / Oriented language called JS in programming language JavaScript code can be run on any normal web browser. To run the code of JavaScript, we have to enable JavaScript of Web Browser. But some web browsers already have JavaScript enabled.

Today almost all websites are using it as web technology, mind is that there is maximum scope in JavaScript in the coming time, so if you want to become a programmer, then you can be very beneficial to learn JavaScript.

JavaScript Hello World Program

In JavaScript, ‘document.write‘ is used to represent a string on a browser.

<script type="text/javascript">
	document.write("Hello World!");
</script>

How to comment JavaScript code?

  • For single line comment in JavaScript we have to use // (double slashes)
  • For multiple line comments we have to use / * – – * /
<script type="text/javascript">

//single line comment

/* document.write("Hello"); */

</script>

Advantages and Disadvantages of JavaScript

#javascript #javascript code #javascript hello world #what is javascript #who invented javascript

Hoang  Ha

Hoang Ha

1660649171

Xây Dựng ứng Dụng Truy Cập Bằng Javascript

JavaScript cho phép bạn tạo các trang web động. Đây là phần cuối cùng của bộ ba phát triển web với HTML và CSS và bạn sử dụng nó để làm cho các trang tĩnh của mình trở nên động.

Bạn có thể sẽ bắt đầu học JavaScript ngay khi bạn đã nắm được các kiến ​​thức cơ bản về HTML và CSS. Sau đó, sau một thời gian, bạn có thể rơi vào một trong các loại sau:

  • Bạn đã học tất cả các cú pháp JavaScript ưa thích nhưng bạn không thể hiểu nó.
  • Bạn hiểu cú pháp nhưng không thể áp dụng nó cho các dự án cá nhân của mình.
  • Bạn muốn nghỉ việc hoặc đang nghĩ đến việc chuyển đổi nghề nghiệp.

Chúng tôi sẽ thực hiện một cách tiếp cận thực tế để học JavaScript trong bài viết này và những bài tiếp theo. Tôi hứa rằng tôi sẽ không làm bạn quá nhiều về cú pháp, mà thay vào đó chúng ta sẽ học bằng cách xây dựng các dự án.

Tôi sẽ giả định rằng bạn biết các nguyên tắc cơ bản của HTML và CSS cho bài viết này và bất kỳ điều nào có thể tuân theo. Nhưng nếu không, bạn có thể tham gia khóa học thân thiện với người mới bắt đầu này để tìm hiểu hoặc trau dồi kiến ​​thức trước khi tiếp tục hướng dẫn này.

Tôi cần công cụ gì để học JavaScript?

JavaScript không yêu cầu thiết lập phức tạp hoặc tốn kém. Tất cả những gì bạn thực sự cần là một chiếc máy tính có những thứ sau:

  • Một trình soạn thảo văn bản (như Visual Studio Code)
  • Trình duyệt web hiện đại (như Chrome, Edge, Firefox, v.v.)

Nếu không có máy tính, bạn vẫn có thể theo dõi bài học bằng cách sử dụng trình soạn thảo mã trực tuyến như codepen.io .

Cách bắt đầu với JavaScript

Như đã nói ở trên, tất cả những gì bạn cần là một trình soạn thảo văn bản và một trình duyệt để bắt đầu. Khởi chạy trình soạn thảo văn bản của bạn — trong trường hợp của tôi là VSCode — trong thư mục mà bạn muốn đặt các tệp mã của mình.

Tạo một tệp mới có tên index.html. Nếu bạn đang sử dụng VS Code, thiết lập dự án của bạn sẽ trông giống như sau:

Ảnh chụp màn hình - 5--1

Cách xem trước mã của bạn trong trình duyệt

Sau khi tạo xong tệp HTML, bạn sẽ muốn xem thành phẩm trong trình duyệt của mình.

Để làm cho quá trình này dễ dàng hơn, chúng tôi cần cài đặt tiện ích mở rộng "máy chủ trực tiếp" trên VS Code. Tiện ích mở rộng này sẽ làm cho trang web ngay lập tức làm mới mỗi khi chúng tôi thực hiện thay đổi đối với tệp HTML của mình.

Nhấp vào biểu tượng tiện ích mở rộng ở phía bên phải của VSCode.

Ảnh chụp màn hình - 7-

Tìm kiếm và cài đặt phần mở rộng máy chủ trực tiếp. Quay lại tệp HTML của bạn và chọn "Mở bằng máy chủ trực tiếp" từ trình đơn ngữ cảnh.

Ảnh chụp màn hình - 8-

Trang web của bạn bây giờ sẽ hiển thị trong trình duyệt của bạn.

Cách nhúng JavaScript vào trang HTML của bạn

Bạn có thể đưa mã JavaScript vào HTML của mình bằng cách đặt nó trực tiếp vào thẻ script.

<!DOCTYPE html>
<html lang="en">
  <head>
    ...
    <script>
      let my_variable = "hello JavaScript";

      // any JavaScript can go in here
    </script>
  </head>
  <body>
    <h1>Hello world</h1>
   
  </body>
</html>

Nhưng hãy nhớ rằng phương pháp trên không được khuyến khích. Thay vào đó, bạn nên tạo một tệp JavaScript bên ngoài có .jsphần mở rộng.

Tạo một tệp mới có tên script.jstrong thư mục dự án của bạn, sau đó liên kết nó với tệp HTML của bạn bằng cách sử dụng URL của mã JavaScript bên ngoài của bạn, như sau:

<!DOCTYPE html>
<html lang="en">
  <head>
   ...
    <script src="script.js"></script>
    <title>Counter</title>
  </head>
  <body>
    ...
  </body>
</html>

JavaScript sẽ thực thi trước bất kỳ HTML nào. Điều này thường gây ra sự cố vì các phần tử HTML bạn chọn với JavaScript sẽ không được xác định vì trình duyệt đọc mã HTML từ trên xuống dưới.

Chúng tôi sẽ sử dụng deferthuộc tính của phần tử script để sửa điều đó, điều này hướng dẫn trình duyệt tải HTML trước trước khi chạy mã JavaScript.

<script defer src="script.js"></script>

Bây giờ chúng ta đã hoàn tất, hãy đi sâu vào một số nguyên tắc cơ bản về JavaScript.

Cách sử dụng các biến trong JavaScript

Một biến là một trình giữ chỗ cho các giá trị mà bạn có thể cần sử dụng trong tương lai. Với JavaScript, mọi thứ được lưu trữ trong các biến.

Để khai báo một biến, bạn có thể sử dụng từ khóa letor .const

let first_variable
const last_variable`

Bạn sử dụng dấu bằng để gán giá trị cho một biến.

let first_variable = “hello world”

Nếu bạn khai báo một biến với let, bạn có thể sửa đổi nó. Mặt khác, nếu bạn khai báo các biến với const, bạn không thể thay đổi giá trị của chúng - do đó có tên.

Trong JavaScript, bạn có thể lưu trữ nhiều kiểu dữ liệu trong các biến:

  • Chuỗi - Bất kỳ giá trị nào là đơn hoặc đôi và được bao bọc trong dấu ngoặc kép là một chuỗi.
let my_string = "Hello world" // string
let my_second_string = "24" // string
  • Số - Những số này không được đặt trong dấu ngoặc kép.
let my_number = 15 // number
let my_second_number = "15" // string
  • Mảng - Mảng là lựa chọn tốt nhất của bạn nếu bạn muốn lưu trữ một số giá trị trong một biến duy nhất.
let my_array = [1, "hello", "4", "world"]

 

  • Boolean - Bạn không cần đặt giá trị boolean trong dấu ngoặc kép vì nó là giá trị true hoặc false chứ không phải là một chuỗi.
let my_boolean = true;

 

  • Đối tượng - Đối tượng cho phép bạn lưu trữ dữ liệu trong các cặp khóa-giá trị.
let my_obj = {
    name: "John snow",
    aim: "Learning JavaScript",
    age: 20,
}

Vì JavaScript diễn giải mọi thứ như một đối tượng, bạn thậm chí có thể lưu các tham chiếu đến các phần tử HTML trong các biến.

let my_button = document.querySelector("#id")

Chúng tôi đang chọn các phần tử trên một trang web dựa trên id của chúng khi chúng tôi sử dụng document.querySelector("#id"). Đừng lo lắng, chúng ta sẽ đi vào chi tiết hơn về vấn đề này sau.

Để sử dụng một biến trong JavaScript, chỉ cần gọi tên biến như sau:

my_button

Để chứng minh cách hoạt động của các biến trong JavaScript, hãy xây dựng một ứng dụng bộ đếm cơ bản. Thêm mã sau vào tệp HTML mà bạn đã tạo trước đó:

...
<body>
    <div class="counter_conatiner">
      <button id="subtract">-</button><span id="output">0</span
      ><button id="add">+</button>
    </div>
  </body>
...

Tạo một style.csstệp và thêm các kiểu sau để tạo sức sống cho tệp bằng cách sử dụng CSS:

*,
*::after,
*::before {
  padding: 0px;
  margin: 0px;
  font-family: inherit;
}
html,
body {
  height: 100vh;
}

body {
  font-family: sans-serif;
  font-size: 16px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background-color: aliceblue;
}
.counter_conatiner {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 6px;
  margin-top: 1rem;
}
span {
  font-size: 3rem;
  background-color: #00bb00;
  padding: 2px 12px;
  margin-left: 16px;
  margin-right: 16px;
  border-radius: 4px;
  color: #fff;
}
button {
  font-size: 3rem;
  cursor: pointer;
  background-color: transparent;
  border: 0px;
}

Đừng quên liên kết tệp CSS với HTML của bạn như sau:

<head>
   ...
    <link rel="stylesheet" href="style.css" />
    <title>Counter</title>
  </head>

Và bạn đã có nó - một ứng dụng truy cập cơ bản được xây dựng bằng HTML và CSS.

Web-capture_13-8-2022_75125_127.0.0.1

Hãy nhớ rằng các biến có thể chứa các tham chiếu đến các phần tử HTML. Bây giờ hãy lưu các tham chiếu đến các nút của chúng ta trong các biến. Mở tệp script.js mà chúng tôi đã tạo trước đó và thêm mã sau vào đó:

let add = document.querySelector("#add");
let subract = document.querySelector("#subtract");

console.log(add, subract);

Chờ một chút, các biến rất thú vị, phải không? Mặc dù chúng có thể chứa bất cứ thứ gì, nhưng có một số nguyên tắc cơ bản mà bạn nên biết trước khi sử dụng các biến:

  • Tránh sử dụng dấu gạch dưới ở đầu tên biến, chẳng hạn như _my_variable, vì chúng rất khó hiểu.
  • JavaScript sẽ không cho phép bạn bắt đầu tên biến bằng số, chẳng hạn như 8_variable.
  • my_variable, MY_VARIABLEmy_Variablelà những thứ hoàn toàn khác trong JavaScript vì phân biệt chữ hoa chữ thường.
  • Và trong mọi trường hợp, bạn không nên sử dụng bất kỳ từ dành riêng nào của JavaScript , bao gồm let, const, true, false, function và bất kỳ từ nào khác.

Này, đừng vi phạm những nguyên tắc cơ bản này. Vì vậy, hãy chuyển sang một số điều thú vị khác mà chúng ta có thể làm bằng JavaScript.

Cách sử dụng các toán tử trong JavaScript

Nếu không có toán học, thế giới sẽ ra sao? Và JavaScript sẽ là gì nếu không có một số phép toán?

Trong JavaScript, chúng tôi có một tập hợp các ký hiệu toán học mà bạn có thể sử dụng để thực hiện các phép toán đơn giản.

Đừng lo lắng, bạn có thể đã quen thuộc với hầu hết chúng:

  • Phép cộng - Trong JavaScript, bạn sử dụng dấu cộng (+) để nối (nối) các chuỗi hoặc thêm số.
let addition = 1 + 1 // 2
let addition = 1 + "1" // "11"
let addition = "hello" + "world" // "hello world"
  • Phép trừ - bạn sử dụng dấu trừ (-) để trừ các số.
let subtraction = 10 - 9 // 1
  • Phép nhân - bạn sử dụng dấu hoa thị cho phép nhân trong JavaScript khi nhân các số.
let multiplication = 2 * 2 // 4
  • Phép chia - bạn sử dụng dấu chia (/) để chia số.
let division = 4 / 2 // 2
  • Bình đẳng - bạn sử dụng dấu bằng kép (==) để kiểm tra xem hai giá trị có bằng nhau trong JavaScript hay không.
let if_true = 2 + 4 == 6 // true
let if_false = 5 + 6 == 10 // false

Có sẵn các toán tử JavaScript khác, nhưng tôi sẽ không đi sâu vào chúng ở đây.

Bây giờ chúng ta đã quen thuộc với các toán tử, hãy quay lại ứng dụng bộ đếm của mình và sửa đổi nó để nó tăng lên bất cứ khi nào chúng ta nhấp vào nút "+" trên trang.

Chúng tôi đã khai báo một số biến và lưu một tham chiếu đến các nút HTML dưới dạng giá trị trong phần trước.

let add = document.querySelector("#add");
let subract = document.querySelector("#subtract");

...

Bây giờ, tất cả những gì chúng ta phải làm để sử dụng addbiến của chúng ta là gọi tên của nó.

add

Nhưng điều này là không đủ. Chúng tôi cần biết nếu nó đã được nhấp vào và JavaScript cung cấp cho chúng tôi những gì chúng tôi gọi là Sự kiện. Chúng tôi sử dụng chúng để lắng nghe các sự kiện xảy ra trên một trang web, chẳng hạn như khi người dùng nhấp vào nút hoặc cuộn xuống trang, trong số những thứ khác.

Đây là những gì nó trông như thế này:

add.addEventListener("click", function () {
 // Every time the add button is pressed, this code will execute.
});

Nó không cần thiết để điều này có ý nghĩa ngay lập tức. Trong trường hợp này, chúng tôi đã sử dụng addEventListenerđể thêm sự kiện nhấp chuột vào nút. Chúng tôi sẽ nói riêng về các sự kiện trong một phần khác.

Bây giờ, bất kỳ mã nào nằm trong lệnh gọi lại của người nghe sẽ được gọi khi nút được nhấp.

Bây giờ chúng ta đã nhận thức được điều này, hãy tăng giá trị đầu ra. Để làm điều này, chỉ cần lấy giá trị đầu ra và sau đó tăng giá trị đó lên một bất cứ khi nào nút được nhấn. Đây là mã để làm điều đó:

let add = document.querySelector("#add");

add.addEventListener("click", function () {
  let output = document.querySelector("#output");
  let result = output.innerText + 1;

  output.innerText = result;
});

Ngoại trừ ký tự innerText, được sử dụng trong JavaScript để lấy văn bản từ các phần tử HTML trên trang web và cũng có thể sửa đổi văn bản của phần tử HTML như đã thấy ở trên, phần lớn cú pháp ở trên bây giờ sẽ dễ nhận biết.

Trong ví dụ dưới đây, hãy nhấp vào nút thêm (+) để xem số gia tăng của bộ đếm.

Không phải những gì bạn dự đoán, phải không? Vì giá trị của   let output = document.querySelector("#output")là một chuỗi và JavaScript không cho phép bạn thêm chuỗi và số, bạn phải chuyển đổi đầu ra thành một số trước khi thêm.

let result = Number(output.innerText) + 1;

Trong đoạn mã trên, chúng tôi đã thay đổi chuỗi của mình thành một số bằng Number()phương thức này.

Hãy thử lại ví dụ trước sau khi chúng tôi đã thực hiện các thay đổi.

Bây giờ nó hoạt động đúng như kế hoạch.

Cách sử dụng các điều kiện trong JavaScript

Chuyện gì xảy ra nếu...? Các điều kiện được sử dụng để giải quyết các câu hỏi như "Điều gì sẽ xảy ra nếu chúng tôi muốn ứng dụng truy cập của chúng tôi ngừng đếm ở mức 10?" hoặc "Nếu chúng ta muốn bỏ qua một số thì sao?" Khi bạn phải đối mặt với những câu hỏi điều kiện như thế này, bạn đang cần một điều kiện.

Các điều kiện duy nhất mà chúng ta sẽ xem xét ngày hôm nay trong JavaScript là câu lệnh if ... else.

if (condition) {
  /* code to run if condition is true */
} else {
  /* run some other code instead */
}

Các điều kiện cho phép chúng tôi chạy mã chỉ khi một điều kiện nhất định được đáp ứng. Ví dụ: nếu bộ đếm của chúng tôi lớn hơn 10, chúng tôi có thể đặt lại nó về không (0).

let add = document.querySelector("#add");

add.addEventListener("click", function () {
  let output = document.querySelector("#output");
  let result = output.innerText + 1;

  if (result > 10) {
    result = 0;
  }

  output.innerText = result;
});

Nếu kết quả lớn hơn 10, câu lệnh if trong đoạn mã trước đó trả về kết quả bằng 0. Trong ví dụ sau, hãy thử tăng bộ đếm lên một số lớn hơn 10.

Bạn sẽ thấy rằng chúng tôi đã bỏ qua câu lệnh else. Đó là bởi vì nó là tùy chọn.

Cách sử dụng các hàm trong JavaScript

Cuối cùng thì chúng tôi cũng đã hoàn thành ứng dụng truy cập nhỏ của mình. Hãy cộng khả năng trừ. Tất cả những gì chúng ta phải làm là trừ đi 1 từ kết quả đầu ra.

let add = document.querySelector("#add");
let subract = document.querySelector("#subtract");

add.addEventListener("click", function () {
  let output = document.querySelector("#output");
  let result = Number(output.innerText) + 1;

  if (result > 10) {
    result = 0;
  }

  output.innerText = result;
});

subract.addEventListener("click", function () {
  let output = document.querySelector("#output");
  let result = Number(output.innerText) - 1;

  if (result < 0) {
    result = 0;
  }

  output.innerText = result;
});

Và bạn đã có nó, một ứng dụng truy cập JavaScript cơ bản.

Hãy xem đoạn mã hoàn chỉnh từ cây bút ở trên và mô tả những gì bạn quan sát được.

Chà, tôi nhận thấy rất nhiều mã trùng lặp, điều này không tốt. Bạn nên tránh lặp lại mã của mình.

Và vì lý do đó, chúng tôi sử dụng các hàm. Chúng ta có thể viết một đoạn mã và sau đó sử dụng nó nhiều lần tùy thích với các hàm.

Bạn có thể sử dụng từ khóa hàm trong JavaScript để tạo một hàm.

function add() {
  alert("hello world")
}

Các hàm cũng có thể nhận tham số.

function add(number1, number2) {
 return number1 + number2
}

Các tham số này được sử dụng giống như các biến trong một hàm. Về cơ bản chúng là trình giữ chỗ.

Các hàm, giống như các biến, được gọi bằng tên của chúng. Sự khác biệt duy nhất là khi gọi một hàm, bạn phải bao gồm dấu ngoặc đơn - ().

add(2,4) // 6

Bạn cũng có thể thấy các hàm được khai báo theo cách này:

const add = (number1, number2) => number1 + number2;

Ở trên tương đương với add()hàm hình thức. Chúng được gọi là các hàm mũi tên, và đó là cách chúng ta sẽ khai báo các hàm của mình từ bây giờ.

Tôi tin rằng đây là đủ thông tin cho phần giới thiệu tại thời điểm này, vì vậy tôi sẽ giao cho bạn nhiệm vụ này.

Thử thách hàng tuần về JavaScript

Chúng tôi đã tạo một ứng dụng đếm đơn giản trong bài học này, nhưng nó chứa rất nhiều mã lặp lại, vì vậy đây là một thách thức dành cho bạn:

  • Tạo một hàm duy nhất được gọi addAndSubtract()có thể xử lý cả các phép toán cộng và trừ mà không cần phải lặp lại bất kỳ mã nào.

Sự kết luận

Trong bài đăng này, chúng tôi đã học cách sử dụng JavaScript, phát triển một ứng dụng bộ đếm nhỏ và tìm hiểu về các biến, điều kiện và hàm.

Ngoài ra, chúc bạn viết mã vui vẻ!

Nguồn: https://www.freecodecamp.org/news/learn-javascript-by-building-a-project/

#javascript