H5 barrier-free adaptation practice in the vivo scene

Author: vivo Internet front-end team - Zhang Li, Dai Wenkuan

As more and more attention is paid to the construction of information barrier-free, developers also encounter more and more challenges in barrier-free adaptation. This article is a practical summary of the author's practice of developing the H5 project in vivo for barrier-free adaptation. This article mainly introduces the barrier-free gestures and barrier-free attributes commonly used in front-end projects, and combines specific development cases to truly demonstrate the adaptation points for developers and provide component adaptation ideas. I hope this article can bring more reference and help to front-end developers.

1. Background

1.1 Cognition of barrier-free adaptation

Accessibility refers to providing fair and equal opportunities and experiences for people of all abilities so that they can more easily access, use and participate in various products, services and environments in society. These individuals include people of all ability levels including physical disabilities, hearing, visual, cognitive and learning disabilities.

1.2 Reasons for barrier-free adaptation

Common impairment types include: visual impairment, hearing impairment, cognitive impairment, and mobility impairment. These "handicapped" groups cannot operate like ordinary people when using software. They may not be able to see clearly and need larger fonts. Depending on visual feedback, it may be inconvenient to operate the body and cannot freely manipulate the phone.

Therefore, the country and enterprises need to think from the perspective of the "disabled" group, and provide fair and equal opportunities and experiences for people of all abilities.

  • [Policy]: The 2011 "Twelfth Five-Year Plan Outline for China's Disabled Persons" pointed out that one of the main tasks of building a barrier-free environment is to strengthen the construction of information barrier-free, and clarified relevant policy measures.

  • 【Inclusiveness】: Accessibility adaptation is an important design and development goal that can help your website or application be more inclusive and accessible.

  • 【Economy】: Barrier-free adaptation is not only a moral obligation, but also an economic benefit, because it can bring a wider audience and better user experience to your website, driving business growth.

1.3 Barrier-free adaptation guidance

In addition to the basic barrier-free adaptations such as large fonts, content broadcasting, speech recognition, subtitles, and voice control supported by the system by default, more page interactions still require front-end engineers to complete the adaptation, so developers need to develop recognizable web pages . page, so that people with disabilities can normally access and use it . This article focuses on barrier-free adaptation for the visually impaired.

2. Barrier-free operation

Before barrier-free development, front-end engineers need to understand barrier-free operation gestures and experience operations from the perspective of disabled people, so as to develop a better interactive experience. It can also avoid development errors and repeated development due to operational errors.

2.1 Screen reader software

First of all, we need to understand the screen-reading devices or software used by the visually impaired. The common screen-reading software is as follows:

picture

Since we are doing barrier-free adaptation of mobile Android phones in vivo phones, the following solutions, cases and other introductions are based on Android-TalkBack.

2.2 Common operating gestures

With the help of TalkBack gestures, you can navigate and perform common operations on Android devices. The following operations are for Android version 9.1 and higher, and are only for vivo phones. Official link: Talkback Gestures .

picture

3. Introduction to common attributes

3.1 aria attribute

The full name of ARIA is "Accessible Rich Internet Applications". It is a technical specification for providing accessible dynamic and interactive web content for persons with disabilities and others. ARIA is used to improve the accessibility of dynamic content and advanced UI controls developed using HTML, CSS, JavaScript, AJAX, and related technologies. ARIA is now officially part of the HTML5 specification and can also be embedded in commonly used JavaScript libraries.

picture

3.2 Aria status

picture

3.3 role attribute

The role marks the element with different attributes, commonly used attributes "button (button), region (graphics)", and broadcasts different content according to different attributes defined.

picture

3.4 tabindex attribute

The use of the tabindex attribute can make the element that cannot get the focus get the focus originally. The intent is to allow the user to access any element that can be accessed with the mouse with the keyboard. We know that using the Tab key can tab to all focusable elements in document order. tabindex can be set to -1, 0 or any natural number.

picture

When the user uses the Tab key to browse the page, the order in which the elements get the focus is arranged according to the order in which the elements appear in the HTML code, and sometimes it is not consistent with the actual page order.

4. Cases of barrier-free adaptation

4.1 Project adaptation case

1. Language settings

The lang attribute in the global <html> element sets the language of the page:

English:

<html lang="en"> 

Chinese:

<html lang="zh-CN"></html>

Domestic Chinese projects generally need to be set to Chinese. If it is set to English, some numbers will be broadcast in English.

2. Hierarchical attributes

If the project has not yet started to adapt, turn on the barrier-free broadcast, and you will find that the tags div and span are the focus and broadcast by default, so the focus and broadcast content are very scattered.

As shown in Figure 2 below, there will be 3 focal points, which are too scattered. Generally, the adaptation will broadcast the ui module as a large focal point. At this time, add tabindex=1 to the outer div to focus.

picture

 Figure 1: Original image

picture

Figure 2: Distraction of focus

picture

Figure 3: A large focal point

Remarks: The green box is the focus mark

(1) Focus broadcast

Because the div tag will broadcast automatically, even if the focus is on the outer layer, the inner layer will still broadcast automatically.

<div class="content"  tabindex="1">
  <div class="amount">
    <div class="num">100</div>
    <div class="unit">元</div>
  </div>
  <div class="desc">话费充值</div>
</div>

Broadcast content: 100 yuan recharge.

(2) Custom broadcast

However, there may be inconsistencies between the content written in the div and the content to be broadcast, then you can write custom content through the aria-label after the outer tabindex="1" is focused

<div class="content" tabindex="1" aria-label="获得100元的话费充值券">
  <div class="amount">
    <div class="num">100</div>
    <div class="unit">元</div>
  </div>
  <div class="desc">话费充值</div>
</div>

Broadcast content: get a 100 yuan recharge coupon

3. Focus Style

Focusing can be achieved through tabindex, but the style will have a yellow border after focusing , which can be removed through outline: none, but there are too many focuses on the page, which can be removed globally.

Set in the public css file:

*[tabindex] {
    outline: none;
}

4. Picture broadcast

(1) The alt attribute setting of the picture

The image is realized through the img tag. If the image cannot be focused, just set alt="" . If it is focusable and needs to broadcast content, it is recommended to set it through aria-label. If you use alt, once the picture cannot be loaded, the alt content will be displayed, and the alt content has no style, which will appear very abrupt on the H5 page.

<img src="close.png" aria-label="关闭" alt=""/>
<img src="dog.png" alt=""/>

(2) Remove the default image attribute (graphics) broadcast

In the img tag, change the role attribute to row

<img
  src="title.png"
  tabindex="1"
  aria-label="超级会员送您1个红包"
  role="row"
/>

5. Button broadcast

Usually, after the button on the ui is selected, it needs to broadcast the button content + button + guide operation (for example: tap twice to activate)

First you need to focus ( tabindex="1" ) to the node, and then you need to write role="button" on the node on the button. After adding this attribute, it will automatically broadcast "button, tap twice to activate"

Case: button in div

picture

<div tabindex="1" role="button" class="btn">立即使用</div>

Announcements: Instantly available, button, double-tap to activate

Case: button in img

picture

<img
  class="btn"
  tabindex="1"
  role="button"
  aria-label="开"
  src="open.png"
/>

Announcement: on, button, double tap to activate

6. Digital broadcast

For example: Mobile phone number: 181****8805 The asterisks in 181****8805 cannot be broadcast correctly, but broadcast as multiplication, and the numbers are broadcast as integers.

Error broadcast: one hundred and eighty-one times times times times eight times eight times five times

It needs to be broadcast correctly: asterisk asterisk asterisk asterisk 8805

You can write a public method to map numbers, * numbers and X number broadcast texts, and call this method in the required conversion method to form mobile phone number broadcast texts.

The public methods are as follows:

function $broadcastNumber(number) {
  if (number === 0) return '零'
  if (!number) return ''
  const numberMap = ['零', '幺', '二', '三', '四', '五', '六', '七', '八', '九']
  const specialMap = { '*': '星号', 'X': '叉号', 'x': '叉号' }
  return number.toString().split('').map(item => numberMap[item] || specialMap[item] || item).join('')
}

7. Custom event broadcast

At present, for nodes with click events, after focusing, they will broadcast the activation by clicking twice by default (system specification), but this guidance is not clear enough, and it is necessary to formulate the broadcast content for specific interaction scenarios, such as: click twice to select, Double tap to open red packets and more.

Solution: Wrap the div in the click event node, write the focus tabindex on the div of this layer, and then customize the content of the broadcast.

<div class="content" tabindex="1" @click="select">
  <div class="amount">
    <div class="num">100</div>
    <div class="unit">元</div>
  </div>
  <div class="desc">话费充值</div>
</div>

Broadcast: 100 yuan recharge, double tap to activate

<div class="content" @click="select">
  <div class="container" tabindex="1" aria-label="获得100元的话费充值券,点按两次即可选中">
    <div class="amount">
      <div class="num">100</div>
      <div class="unit">元</div>
   </div>
  <div class="desc">话费充值</div>
 </div>
</div>

Broadcast: get a 100 yuan recharge coupon, tap twice to select

8. Additional content broadcast

Such as: which item, how many items in total, click twice to select

picture

Solution: It can be realized with empty div and aria-label

<div class="content" @click="select">
  <div class="container" :class="{ 'z-active' : code === item.code }" tabindex="1">
    <div v-if="code === item.code" aria-label="已选中"></div>
    <div class="amount">
      <div class="num">{
   
   { item.num }}</div>
      <div class="unit">元</div>
    </div>
    <div class="desc">{
   
   { item.desc }}</div>
    <div :aria-label="`第${index+1}项,共${list.length}项,${code === item.code? '' : '点按两次即可选中'}`"></div>
  </div>
</div>

9. Overall broadcast

Usually, the content of the overall broadcast is more, and the order of the broadcast is not the order of the code writing. At this time, it is necessary to control the content of the broadcast in the outer focus, mainly through two methods, aria-label splicing parameters and aria-labelledby setting id.

picture

What needs to be broadcast: telephone recharge coupons, 50 yuan discount coupons, can be used when you spend 199 yuan, use it immediately.

(1) aria-label stitching parameters

After setting tabindex=1 in the outer node, add the aria-label attribute to add parameters in the required order

case:

<div class="content" tabindex="1" :aria-label="`${title}${num}元${type}${rule}${btn}`">
  <div class="left">
    <div class="amount">
      <span class="num">{
   
   { num }}</span>
      <span class="unit">元</span>
    </div>
    <div class="type">{
   
   { type }}</div>
  </div>
  <div class="right">
    <div class="desc">
      <div class="title">{
   
   { title }}</div>
      <div class="rule">{
   
   { rule }}</div>
    </div>
    <div role="button" class="btn">{
   
   { btn }}</div>
  </div>
</div>

(2) aria-labelledby set id

After setting tabindex=1 in the outer node, add the id value in the content node that needs to be broadcast, and write the id value in the aria-labelledby attribute of the outer node in the required order

case:

<div class="content" tabindex="1" aria-labelledby="title amount type rule btn">
  <div class="left">
    <div id="amount" class="amount">
      <span class="num">{
   
   { num }}</span>
      <span class="unit">元</span>
    </div>
    <div id="type" class="type">{
   
   { type }}</div>
  </div>
  <div class="right">
    <div class="desc">
      <div id="title" class="title">{
   
   { title }}</div>
      <div id="rule" class="rule">{
   
   { rule }}</div>
    </div>
    <div id="btn" role="button" class="btn">{
   
   { btn }}</div>
  </div>
</div>

10. Partial special broadcast

For example, in the coupon module, you can select and broadcast all coupon content as a whole, but the internal immediate use button can also focus on broadcasting and jumping.

picture

Solution: Focus on the outer layer - set tabindex=1, set aria-label splicing parameters or aria-labelledby to set id for the whole broadcast content, focus on the inner part of the content, set tabindex=1 for the focused content, and set aria-hidden= for the unfocused part "true" (otherwise, when the outer focus is selected, the inner unfocused part will be broadcast repeatedly).


<div class="content" tabindex="1" aria-labelledby="title amount type rule btn">
  <div class="left" aria-hidden="true">
    <div id="amount" class="amount">
      <span class="num">{
   
   { num }}</span>
      <span class="unit">元</span>
    </div>
    <div id="type" class="type">{
   
   { type }}</div>
  </div>
  <div class="right">
    <div class="desc" aria-hidden="true">
      <div id="title" class="title">{
   
   { title }}</div>
      <div id="rule" class="rule">{
   
   { rule }}</div>
    </div>
    <div id="btn" tabindex="1" role="button" class="btn">{
   
   { btn }}</div>
  </div>
</div>

11. Solve the problem that after setting aria-labelledby="[id]" in the component, only the content of the first piece of data will be broadcast repeatedly

Because the component is called by the template for loop in Vue, each content is different. Using the same id will cause the same content to be broadcast, and there is no distinction between key values. It needs to be resolved after setting aria-labelledby="[id]" and only repeating Broadcast the content of the first piece of data

At this time, the id needs to be distinguished according to the unique identifier: the unique identifier number can be spliced ​​after the id, such as: "`amount-${item.id}`"

case:

<div class="content" tabindex="1" :aria-labelledby="`amount-${item.id} desc-${item.id}`">
  <div id="amount" class="amount">{
   
   { item.amount }}</div>
  <div id="desc" class="desc">{
   
   { item.desc }}</div>
</div>

4.2 Component adaptation case

In addition to specific business adaptation, there are some common component issues that require unified adaptation of the component library, which can reduce the workload of individual adaptation for each business.

The adaptation of any barrier-free component includes two parts: broadcast content management and focus management. For broadcast content management, almost all component adaptations will be involved. Barrier-free aria role and states Generally, the system has its own default broadcasting behavior, try to keep the system's default broadcasting behavior. Of course, you can also customize the broadcast content through aria-label. Focus management is mainly aimed at components whose elements will change, such as pop-up windows, carousels, and various selectors.

There are three basic methods of focus management:

  1. tabindex attribute;

  2. aria-hidden attribute;

  3. el. focus() method.

tabindex="undefined" means that the element cannot be focused, and other values ​​mean that the element can be focused. aria-hidden is true, which means it cannot be focused and will not broadcast. For focusable elements, you can directly focus on the element through the el.focus() method.

The following uses a typical case to illustrate how each component handles focus and broadcast content. In addition, since the same component may be used multiple times in an html, the following cases are all adapted without using the id attribute. If you must use the id attribute in a certain component, remember to randomly name the id attribute through a random function.

1. switch, checkbox, radio components

These components are relatively simple, just use the default role of the system. Just complete the adaptation of the broadcast content, and do not need to do focus management.

Take switch as an example: first, role=switch, then use aria-check to broadcast the switch status, and finally use aria-disabled to broadcast whether it is disabled.

<div
  class="nx-switch"
  tabindex="-1"
  :aria-checked="!!value"
  :aria-disabled="disabled"
  @click="onClick"
  role="switch"
>
  <div :style="barStyle"></div>
  <div :style="ringStyle"></div>
</div>

2. Pop-up window and dialog box components

The pop-up window component is a relatively complex component, which involves both focus management and broadcast content management. The pop-up window component mainly introduces the tips of focus management.

The usage of this component in business:

Our pop-up window components are relatively common, mainly including three parts: title, content, and button. Among them, the title and content can be passed in through attributes or slots. For the incoming part of the slot, the component is not easy to control. In the process of business use, pop-up windows with only content are common.

Adaptation goal: When the pop-up window pops up, it needs to automatically focus on the title and broadcast it.

Pop-up window focus order: When the pop-up window pops up, it needs to automatically focus on the title and read the title aloud, then manually move the next focus to focus on the explanatory text, and finally focus on the operation button.

picture

(1) Focus management

First of all, it is necessary to solve the focus problem when the pop-up window pops up. Because the pop-up window component is very flexible, the usage scenarios are also very diverse. For the title passed in by the attribute, the element can be obtained inside the component, and the focused broadcast can be completed; it is powerless for slot insertion.

For the case of slot, the component and the business agree on an attribute. If the business wants to focus on this dom element, add this attribute to the element. The component will query the descendant elements of the pop-up window through el.querySelector , automatically add tabindex and complete the focused broadcast when the pop-up window pops up.

<nx-popup v-model="isPopupShow.center">
  <div
    nx-popup-aria-auto-focus="true"
    aria-label="无障碍播报测试"
    class="nx-popup-center"
  >
    Popup Center
  </div>
</nx-popup>

In addition, considering that there is a business requirement not to automatically focus on the pop-up window when it pops up, an attribute is also provided to turn off the focus management function.

Then, it is necessary to solve the focus restoration problem when the pop-up window is closed. Save the currently focused element document.activeElement before the pop-up window pops up. After closing the pop-up window, manually focus on the element through el.focus().

There is one problem of focus penetration left. The aria-modal attribute of many Android systems does not work, so the focus can still penetrate the pop-up window and select elements on the page.

There is currently no particularly good way for components to handle this. During the development process, you can add the aria-hidden=true attribute to the elements that need to be shielded

(2) Broadcast content management

This part seems relatively simple. In the case of slots, the broadcast content can be handed over to business development and control; in the case of attribute input, component attributes can be added to provide the business with the ability to customize broadcasts.

3. Address selector component

The address picker is a scrollable interactive component. In the development process of this component, a small trick is used, that is, it can automatically broadcast the content of the element change without focusing on an element.

The use of this component in business: business development does not customize this component, so only the internal adaptation of the component needs to be considered.

Adaptation target: Automatically focus on the title and broadcast when the pop-up window pops up. The figure below shows the layout of the focal points.

picture

Take this picture as an example, when the focus is on the first column, it will broadcast "Hebei Province, slide the wheel control, you can scroll up and down to switch"; in addition, at the end of each column scrolling, broadcast the currently selected address, such as "Hebei Province, Shijiazhuang City, Qiaoxi District”

(1) Focus management

Same as the pop-up window component.

(2) Broadcast content management

The difficulty here is that when the scrolling of each column ends, the changed address needs to be broadcast, but the focus is still on the selected column at this time.

A hidden element (not displayed on the page) is added here, and the attribute aria-live="polite " is added to modify the value of ariaPickerContent when the scroll ends . If you don't want to broadcast, set ariaPickerContent to an empty string, and remember to set it to empty when the pop-up window is closed.

<div class="nx-picker-scroll-aria" aria-live="polite">
  {
   
   { ariaPickerContent }}
</div>

V. Summary

This article is the practice of barrier-free adaptation under the vivo system. It mainly extracts and summarizes some adaptation methods, which have certain reference and reference value for internal and external barrier-free adaptation work. The next step is to enrich and improve the adaptation of the component library, deposit a set of efficient adaptation solutions, minimize the adaptation cost of developers, and improve development efficiency.

Developers should uphold an attitude of warmth in technology and love in code, adhere to the principle of "don't do something small, and be user-oriented, let our products and services illuminate every user, and let "disabled groups" "In this loving Internet age, keep up with the trend of the times.

Guess you like

Origin blog.csdn.net/vivo_tech/article/details/132204289