# 網站無障礙規範 以下是所有無障礙指引 [套件Document- eslint-plugin-jsx-a11y ](https://www.npmjs.com/package/eslint-plugin-jsx-a11y?activeTab=readme) [十三指引(WCAG)規範](https://accessibility.moda.gov.tw/Accessible/Guide/68) [台灣NCC無障礙的規範](https://accessibility.moda.gov.tw/AppCases/Index.aspx) ## Eslint a11y 盤點 ### jsx-a11y/alt-text | rules || | -------- | -------- | |說明| `<img>` 一定要有 alt 屬性並加上文字說明,若為裝飾性的img也必須給上空字串。預設情況下,此規則檢查`<img>,<area>,<input type="image">,<object>` 這些元素的alt-text。 | | elements | "img", "object", "area", "`input[type=\"image\"]`" | | 對應指引 | 成功準則1.1.1:非文字內容 (檢測等級A) | |NCC-APP 識別碼| AT1,AT2...AT7 | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/alt-text.md | ```htmlmixed! // image <img src="foo" alt="Foo eating a sandwich." /> <img src="foo" alt={"Foo eating a sandwich."} /> <img src="foo" alt={altText} /> <img src="foo" alt={`${person} smiling`} /> // 對於用來作為按鈕圖像的image,alt prop 應設置為空字符串(alt="")。 <button> <img src="icon.png" alt="" /> Save </button> // object 有以下四種設定方式: <object aria-label="foo" /> <object aria-labelledby="id1" /> <object>Meaningful description</object> //inner text <object title="An object" /> // area 有以下三種設定方式: <area aria-label="foo" /> <area aria-labelledby="id1" /> <area alt="This is descriptive!" /> // input[type="image"] // 必須設定"非空值"的alt屬性,或是aria-label or aria-labelledby props <input type="image" alt="This is descriptive!" /> <input type="image" aria-label="foo" /> <input type="image" aria-labelledby="id1" /> ``` --- ### jsx-a11y/anchor-ambiguous-text | rules | | | -------- | -------- | | 說明 | 必須解釋此連結的目的,禁止使用不夠語意化、意圖模糊的文字在`<a>`元素中,預設會比對這些關鍵字 ['click here', 'here', 'link', 'a link', 'learn more'],比對的規則是case-insensitive(不分大小寫) | | 預設關鍵字 | "click this", "click here", "here", "link", "a link", "learn more", | 對應指引 | General best practice ([reference resources](https://webaim.org/techniques/hypertext/#screen_readers)) | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/anchor-ambiguous-text.md | ```htmlmixed! // 1.會優先比對aria-label其次innerText // 2.或是有aria-hidden="true就跳過此a元素 // 3.如果a元素沒有innerText但有子層元素<img>,<span>,<i>...等,則將子元素視為父層的innerText來檢查 // 以下三種Succeed的範例: <a>read this tutorial</a> // 通過,因為innerText文字不在禁止使用的list中 <a>${here}</a> // this is valid since 'here' is a variable name <a aria-label="tutorial on using eslint-plugin-jsx-a11y">click here</a> // the aria-label supersedes the inner text ``` --- ### jsx-a11y/anchor-has-content | rules | | | -------- | -------- | | 說明 | 為避免screen reader無法念出anchor的內容,此規則會檢核a是否有內容 | | components | "Anchor" | | 對應指引 | 成功準則2.4.4:鏈結目的(脈絡) (檢測等級A) <br> 成功準則2.4.5:多種方式 (檢測等級AA) | |NCC-APP 識別碼| LK1/LK2(2.4.4)<br> | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/anchor-has-content.md | ```htmlmixed! // Succeed <a>Anchor Content!</a> <a dangerouslySetInnerHTML={{ __html: 'foo' }} /> <a><TextWrapper /></a> // 這樣會failed <a><TextWrapper aria-hidden /></a> ``` --- ### jsx-a11y/anchor-is-valid | rules | | | -------- | -------- | | 說明 | anchor就是用來導向的一種element(hyperlink),若只是為了"點擊互動"請改用button/span/div等其他element達成| | 對應指引 | 成功準則2.1.1:鍵盤 (檢測等級A) | |NCC-APP 識別碼| FC1 | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/anchor-is-valid.md | 建議閱讀文件說明,有依據不同case情境提供建議的做法 ```htmlmixed! // Succeed <a href="https://github.com" /> <a href="#section" /> <a href="foo" /> <a href="/foo/bar" /> <a href={someValidPath} /> <a href="https://github.com" onClick={foo} /> <a href="#section" onClick={foo} /> <a href="foo" onClick={foo} /> <a href="/foo/bar" onClick={foo} /> <a href={someValidPath} onClick={foo} /> // 請避免以下三種用法: // 1. 把anchor當作button使用 <a href="#" onClick={foo} /> // 2. 沒有href prop <a href={undefined} /> // 3. href使用無效的值,請改用button/span/div等其他element點擊互動目的 <a href="javascript:void(0)" /> ``` --- ### jsx-a11y/aria-activedescendant-has-tabindex | rules | | | -------- | -------- | | 說明 | 用於複合式元件,父元件設定aria-activedescendant屬性,並用子層ID設定為值,表示當focus到父層元件後,使用tab/arrow就會focus到所設定的子層。| | 對應指引 | General best practice (reference resources) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/aria-activedescendant-has-tabindex.md | >[tabindex用法解說](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Global_attributes/tabindex): > - tabindex=負值 (通常是 tabindex=“-1”),表示元素是能被focus,但是不能用鍵盤(tab之類)navigate到該元素 > - tabindex=正值,表示元素是能被focus,且可以用鍵盤navigate到該元素 ```htmlmixed! // Succeed <div /> <div tabIndex={0} /> <div aria-activedescendant={someID} tabIndex={0} /> <div aria-activedescendant={someID} tabIndex="0" /> <div aria-activedescendant={someID} tabIndex={1} /> // Fail! <div aria-activedescendant={someID} /> <div aria-activedescendant={someID} tabIndex={-1} /> <div aria-activedescendant={someID} tabIndex="-1" /> // Succeed <input /> <input aria-activedescendant={someID} /> <input aria-activedescendant={someID} tabIndex={0} /> // Fail! <input aria-activedescendant={someID} tabIndex={-1} /> // Succeed <CustomComponent /> <CustomComponent aria-activedescendant={someID} /> <CustomComponent aria-activedescendant={someID} tabIndex={0} /> <CustomComponent aria-activedescendant={someID} tabIndex={-1} /> ``` --- ### jsx-a11y/aria-props | rules | | | -------- | -------- | | 說明 | 元素不能使用無效的 ARIA 屬性。如果找到`aria-*`未在WAI-ARIA States and Properties spec中列出的屬性,就會檢核失敗。 | | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/aria-props.md | ```htmlmixed! // Good: Labeled using correctly spelled aria-labelledby <div id="address_label">Enter your address</div> <input aria-labelledby="address_label"> // Bad: Labeled using incorrectly spelled aria-labeledby <div id="address_label">Enter your address</div> <input aria-labeledby="address_label"> ``` --- ### jsx-a11y/aria-proptypes | rules | | | -------- | -------- | | 說明 | aria 狀態和屬性值必須有效。 | | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/aria-proptypes.md | ```htmlmixed! // Good: the aria-hidden state is of type true/false <span aria-hidden="true">foo</span> // Bad: the aria-hidden state is of type true/false <span aria-hidden="yes">foo</span> ``` --- ### jsx-a11y/aria-role | rules | | | -------- | -------- | | 說明 | 若有使用aria-role,則須符合[role所定義的種類](https://www.w3.org/TR/wai-aria/#role_definitions) | | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/aria-role.md | ```htmlmixed! // Succeed <div role="button"></div> // Good: "button" is a valid ARIA role <div role={role}></div> // Good: role is a variable & cannot be determined until runtime. <div></div> // Good: No ARIA role <Foo role={role}></Foo> // Good: ignoreNonDOM is set to true // Fail <div role="datepicker"></div> // Bad: "datepicker" is not an ARIA role <div role="range"></div> // Bad: "range" is an _abstract_ ARIA role <div role=""></div> // Bad: An empty ARIA role is not allowed <Foo role={role}></Foo> // Bad: ignoreNonDOM is set to false or not set ``` --- ### jsx-a11y/aria-unsupported-elements | rules | | | -------- | -------- | | 說明 | 某些HTML tag並不是用來讓使用者觀看,例如:`meta`, `html`, `script`, `style`,所以禁止使用`role`和`aria-*`props在這些標籤上| | 對應指引 |成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1 | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/aria-unsupported-elements.md | ```htmlmixed! <!-- Good: the meta element should not be given any ARIA attributes --> <meta charset="UTF-8" /> <!-- Bad: the meta element should not be given any ARIA attributes --> <meta charset="UTF-8" aria-hidden="false" /> ``` --- ### jsx-a11y/autocomplete-valid | rules | | | -------- | -------- | | 說明 | 若會沒有提供正確autocomplete值,螢幕閱讀器就會無法正確的讀取表單內容給使用者,所以會檢核form表單在使用autocomplete屬性的正確性 | | 對應指引 | 成功準則1.3.5:識別輸入目的 (檢測等級AA) | |NCC-APP 識別碼| FM2 | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/autocomplete-valid.md | > 延伸閱讀[autocomplete的使用規則](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Attributes/autocomplete) ```htmlmixed! <!-- Good: the autocomplete attribute is used according to the HTML specification --> <input type="text" autocomplete="name" /> <!-- Good: MyInput is not listed in inputComponents --> <MyInput autocomplete="incorrect" /> <!-- Bad: the autocomplete attribute has an invalid value --> <input type="text" autocomplete="incorrect" /> <!-- Bad: the autocomplete attribute is on an inappropriate input element --> <input type="email" autocomplete="url" /> <!-- Bad: MyInput is listed in inputComponents --> <MyInput autocomplete="incorrect" /> ``` --- ### jsx-a11y/click-events-have-key-events | rules | | | -------- | -------- | | 說明 | 有些使用者因為無法用滑鼠操作網頁,在撰寫`onClick`事件時,必須搭配keyboardEvent的使用:`onKeyUp`, `onKeyDown`, `onKeyPress`,確保鍵盤使用者在"點擊事件"的可用性。若為hidden element就不會被檢核 | | 對應指引 | 成功準則2.1.1:鍵盤 (檢測等級A) | |NCC-APP 識別碼| FC1 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/click-events-have-key-events.md| ```htmlmixed! // Succeed <div onClick={() => {}} onKeyDown={this.handleKeyDown} /> <div onClick={() => {}} onKeyUp={this.handleKeyUp} /> <div onClick={() => {}} onKeyPress={this.handleKeyPress} /> <button onClick={() => {}} /> <div onClick{() => {}} aria-hidden="true" /> // Fail <div onClick={() => {}} /> ``` --- ### jsx-a11y/control-has-associated-label | rules | | | -------- | -------- | | 說明 | 為了讓螢幕閱讀器能正確的讀取元素資訊,會檢核互動元件是否都有加上對應的文字說明。 | | 對應指引 | 成功準則1.3.1:資訊與關連性 (檢測等級A)<br>成功準則3.3.2:標籤或說明 (檢測等級A)<br>成功準則4.1.2:名稱、角色和值 (檢測等級A)| |NCC-APP 識別碼| FM1/FM3(3.3.2)<br>NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/control-has-associated-label.md | ```htmlmixed! 有以下幾種使用方式: 1. 元素是否有提供innerText,若子層是img可用使用alt來描述內容 2. 使用aria-label="文字說明" 3. 使用aria-labelledby並指向到對應的元素 // case1: 可以直接使用innerText當作說明 <button type="button">Save</button> // case2: 設計上不想要有文字呈現時,可以改用aria-label來描述 <button type="button" aria-label="Save" class="icon-save" /> // case3: 元件說明已經在頁面上,不想重複文字說明,可以用aria-labelledby指向到關聯的element <div id="js_1">Comment</div> <textarea aria-labelledby="js_1"></textarea> ``` 客製化元件也可以透過config設定,啟用這項rule(jsx-a11y/control-has-associated-label)的檢核  [rule options寫法](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/control-has-associated-label.md#rule-options) ```htmlmixed! // config的"labelAttributes": ["label"] 對應到下面的prop <CustomInput label="Surname" type="text" value={value} /> ``` --- ### jsx-a11y/heading-has-content | rules | | | -------- | -------- | | 說明 | 強制`<h1>-<h6>`標籤必須要有內容,且不能使用aria-hidden讓螢幕閱讀器讀取不到。| | 對應指引 | 成功準則2.4.6:標題和標籤 (檢測等級AA) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/heading-has-content.md | ```htmlmixed! // Succeed <h1>Heading Content!</h1> <h1><TextWrapper /><h1> <h1 dangerouslySetInnerHTML={{ __html: 'foo' }} /> ``` 若為客製化的標題元件,可以透過config設定啟用"jsx-a11y/heading-has-content"檢核 ```jsonld! { "rules": { "jsx-a11y/heading-has-content": [ 2, { "components": [ "MyHeading" ], }], } } ``` ```javascript! // MyHeading.js const MyHeading = props => { return ( <h1 {...props}>{ props.children }</h1> ); } ... // CreateAccount.js (for example) ... return ( <MyHeading>Create Account</MyHeading> ); ``` --- ### jsx-a11y/html-has-lang | rules | | | -------- | -------- | | 說明 | 如果網頁沒有指定語言,螢幕閱讀器就會使用使用者的預設語言閱讀文件,有可能導致發音聽起來很奇怪,如果螢幕閱讀器使用了錯誤的語言庫閱讀,會讓使用者很難理解網站內容。 | | 對應指引 | 成功準則3.1.1:網頁語言 (檢測等級A)| |NCC-APP 識別碼| PD1 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/html-has-lang.md| ```htmlmixed! // Succeed <html lang="en"> <html lang="en-US"> <html lang={language}> // Fail <html> ``` --- ### jsx-a11y/iframe-has-title | rules | | | -------- | -------- | | 說明 | 使用iframe必須加上title說明 | | 對應指引 | 成功準則2.4.1:跳過區塊 (檢測等級A)<br>成功準則4.1.2:名稱、角色和值 (檢測等級A)| |NCC-APP 識別碼| NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/iframe-has-title.md | ```htmlmixed! // Succeed <iframe title="This is a unique title" /> <iframe title={uniqueTitle} /> // Fail <iframe /> <iframe {...props} /> ``` --- ### jsx-a11y/img-redundant-alt | rules | | | -------- | -------- | | 說明 | 強制要求 img 的 alt 屬性不含有「image」、「picture」或「photo」等詞語。螢幕閱讀器已經會把 img 元素宣告為圖像,因此不需要使用「image」、「photo」和/或「picture」等詞語。但該規則首先會檢查 aria-hidden 是否為 true,若為true就不執行該規則。 | | 對應指引 | General best practice (reference resources) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/img-redundant-alt.md | > redundant: unnecessary because it is more than is needed >多餘的,不需要的,累贅的,囉唆的 ```htmlmixed! // Succeed <img src="foo" alt="Foo eating a sandwich." /> <img src="bar" aria-hidden alt="Picture of me taking a photo of an image" /> // Will pass because it is hidden. <img src="baz" alt={`Baz taking a ${photo}`} /> // This is valid since photo is a variable name. // Fail <img src="foo" alt="Photo of foo being weird." /> <img src="bar" alt="Image of me at a bar!" /> <img src="baz" alt="Picture of baz fixing a bug." /> ``` 可以透過config設定要檢查的關鍵字 ```jsonld! { "rules": { "jsx-a11y/img-redundant-alt": [ 2, { "components": [ "Image" ], "words": [ "Bild", "Foto" ], // Bild德文”圖片“ // Foto印尼文“圖片” }], } } ``` --- ### jsx-a11y/interactive-supports-focus | rules | | | -------- | -------- | | 說明 | 元素若可以互動(滑鼠事件/鍵盤事件)則必須要可以被focus | | 對應指引 | 成功準則2.1.1:鍵盤 (檢測等級A) | |NCC-APP 識別碼| FC1 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/interactive-supports-focus.md 建議閱讀文件內的case說明 | - 可以設定以下幾種解法: - ==tabbable:== 1. 設定tabIndex 2. 使用語意化的HTML: `<button>`, `<a href>` or `<input>` - ==focusable:== 1. 建議閱讀[W3建議的元件設計](https://www.w3.org/WAI/ARIA/apg/patterns/) 2. 鍵盤使用者是透過tab來focus元件,但有些group元件為符合設計會需要設定tabIndex=-1(可以focusable但不行tabbable),這時就會需要自行撰寫鍵盤事件(key (up/down/left/right) presses)去切換下一個的focus 3. 父層可設定role="presentation"讓輔助器忽略,避免因為子層event bubbled重複觸發 ```htmlmixed! // Succeed <!-- Good: div with onClick attribute is hidden from screen reader --> <div aria-hidden onClick={() => void 0} /> <!-- Good: span with onClick attribute is in the tab order --> <span onClick="doSomething();" tabIndex="0" role="button">Click me!</span> <!-- Good: span with onClick attribute may be focused programmatically --> <span onClick="doSomething();" tabIndex="-1" role="menuitem">Click me too!</span> <!-- Good: anchor element with href is inherently focusable --> <a href="javascript:void(0);" onClick="doSomething();">Click ALL the things!</a> <!-- Good: buttons are inherently focusable --> <button onClick="doSomething();">Click the button :)</button> // Fail <!-- Bad: span with onClick attribute has no tabindex --> <span onclick="submitForm();" role="button">Submit</span> <!-- Bad: anchor element without href is not focusable --> <a onclick="showNextPage();" role="button">Next page</a> ``` --- ### jsx-a11y/label-has-associated-control | rules | | | -------- | -------- | | 說明 | 強制label標籤一定要包含相關的dom內容,或是使用for屬性關聯對應的dom | | 對應指引 | 成功準則1.3.1:資訊與關連性 (檢測等級A)<br> 成功準則3.3.2:標籤或說明 (檢測等級A)<br>成功準則4.1.2:名稱、角色和值 (檢測等級A)| |NCC-APP 識別碼| FM1/FM3(3.3.2)<br>NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/label-has-associated-control.md | ```htmlmixed! 以下兩種方式都可行: <label> Surname <input type="text" /> </label> <label htmlFor={domId}>Surname</label> <input type="text" id={domId} /> // 若為客製化元件則可以這樣撰寫,並設定config rule檢核 <CustomInputLabel label="Surname"> <CustomInput type="text" value={value} /> </CustomInputLabel> ``` jxs元件寫法參考 ```htmlmixed! // Fail function Foo(props) { return <label {...props} /> } // Succeed function Foo(props) { const { htmlFor, ...otherProps } = props; return <label htmlFor={htmlFor} {...otherProps} /> } ``` --- ### jsx-a11y/media-has-caption | rules | | | -------- | -------- | | 說明 | 強制要求影片`<video>`或音訊`<audio>`必須提供字幕(caption內容)`<track kind="captions"/>`,若video有mute屬性時,就不強制要求有caption | | 對應指引 | 成功準則1.2.2:字幕(預錄) (檢測等級A)<br>成功準則1.2.3:音訊描述或替代媒體 (檢測等級A)| |NCC-APP 識別碼| AV1 | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/media-has-caption.md | ```htmlmixed! // Succeed <audio><track kind="captions" {...props} /></audio> <video><track kind="captions" {...props} /></video> <video muted {...props} ></video> // Fail <audio {...props} /> <video {...props} /> ``` --- ### jsx-a11y/mouse-events-have-key-events | rules | | | -------- | -------- | | 說明 | 對於不能使用鼠標的身體殘疾用戶會使用鍵盤操作,所以強制 onmouseover/onmouseout 伴隨著 onfocus/onblur事件撰寫 | | 對應指引 | 成功準則2.1.1:鍵盤 (檢測等級A) | |NCC-APP 識別碼| FC1 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/mouse-events-have-key-events.md | ```htmlmixed! // Succeed <div onMouseOver={ () => void 0 } onFocus={ () => void 0 } /> <div onMouseOut={ () => void 0 } onBlur={ () => void 0 } /> <div onMouseOver={ () => void 0 } onFocus={ () => void 0 } {...otherProps} /> <div onMouseOut={ () => void 0 } onBlur={ () => void 0 } {...otherProps} /> // Fail <div onMouseOver={ () => void 0 } /> <div onMouseOut={ () => void 0 } /> <div onMouseOver={ () => void 0 } {...otherProps} /> <div onMouseOut={ () => void 0 } {...otherProps} /> ``` --- ### jsx-a11y/no-access-key | rules | | | -------- | -------- | | 說明 | 禁止使用accessKey屬性在html中,因為鍵盤使用者會不小心誤觸發我們所設定的accessKey,進而導致操作上的錯誤發生。 | | 對應指引 | General best practice (reference resources) | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-access-key.md | ```htmlmixed! // Succeed <div /> // Fail <div accessKey="h" /> ``` --- ### jsx-a11y/no-autofocus | rules | | | -------- | -------- | | 說明 | 禁用autofocus屬性(一般用在focus表單欄位),視覺障礙使用者看不見autofocus的內容 | | 對應指引 | General best practice (reference resources) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-autofocus.md | ```htmlmixed! // Succeed <div /> // Fail <div autoFocus /> <div autoFocus="true" /> <div autoFocus="false" /> <div autoFocus={undefined} /> ``` --- ### jsx-a11y/no-distracting-elements | rules | | | -------- | -------- | | 說明 | 禁止使用會干擾視覺的DOM元素,預設禁用`marquee`, `blink`元素 | | 對應指引 | 成功準則2.2.2:暫停、停止和隱藏 (檢測等級A) | |NCC-APP 識別碼| DC2/DC4(2.2.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-distracting-elements.md | >[<marquee>:捲動元素](https://developer.mozilla.org/zh-TW/docs/Web/HTML/Element/marquee) > [<blink>:文字閃爍元素](https://developer.mozilla.org/zh-TW/docs/Web/HTML/Element/blink) ```htmlmixed! // Succeed <div /> // Fail <marquee /> <blink /> ``` --- ### jsx-a11y/no-interactive-element-to-noninteractive-role | rules | | | -------- | -------- | | 說明 | 此規則會比對[WAI-ARIA Roles](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)([MDN列表參考](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles))的設定是否正確,針對" Non-interactive"元素有正確的設定"Non-interactive ARIA roles",因為有互動性(Interactive HTML)的元件表示能與使用者互動,若設定錯誤會造成使用者困擾 | | 對應指引 |成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-interactive-element-to-noninteractive-role.md | - 有互動性(Interactive HTML)的元件有: `<a href>`, `<button>`, `<input>`, `<select>`, `<textarea>`等. - 無互動的元件有:`<main>`, `<area>`, `<h1-h6>`, `<img>`, `<li>`, `<ul>` and `<ol>`等. > HTML本身會自帶role的意義,對照請參考:https://www.w3.org/TR/html-aria/#docconformance - 無互動WAI-ARIA roles值有:`article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`等. ```htmlmixed! // 如果想在Button(interactive element)加上role,則需要多包一層div來設定 <div role="article"> <button>Save</button> </div> // Non-interactive ARIA roles 可放在 interactive element裡 <div role="button" onClick={() => {}} onKeyPress={() => {}} tabIndex="0"> <div role="img" aria-label="Save" /> </div> ``` --- ### jsx-a11y/no-noninteractive-element-interactions | rules | | | -------- | -------- | | 說明 | 此規則會檢核==noninteractive-role==的DOM禁止設定==event handler==,因為非互動性DOM通常代表著content或是container的意涵,所以基本上不能設定event handler(**事件種類如下列表**)於該DOM上 | | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-noninteractive-element-interactions.md 建議閱讀文件內的case說明 | - **預設檢查的events**:`onClick`, `onMouseDown`, `onMouseUp`, `onKeyPress`, `onKeyDown`, `onKeyUp` - Non-interactive WAI-ARIA roles 有 `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip`. - Non-interactive elements 有 `<main>`, `<area>`, `<h1-h6>`, `<p>`, `<img>`, `<li>`, `<ul>` and `<ol>`. ```htmlmixed! <!-- Case: 若有Non-interactive role想設定event該如何寫? --> // 可多包一層,透過子層設定onClick且role="presentation",讓父層依然Non-interactive(article) // 當role="presentation" 螢幕閱讀器不會將該元素視為一個具有語義的元素,就不會去讀取 <div role="article"> <div onClick="onClickHandler" onKeyPress={onKeyPressHandler} role="presentation"> {this.props.children} </div> </div> // Succeed <div onClick={() => void 0} role="button" /> <div onClick={() => void 0} role="presentation" /> <input type="text" onClick={() => void 0} /> // Interactive element does not require role. <button onClick={() => void 0} className="foo" /> // button is interactive. <div onClick={() => void 0} role="button" aria-hidden /> // This is hidden from screenreader. <Input onClick={() => void 0} type="hidden" /> // This is a higher-level DOM component // Fail <li onClick={() => void 0} /> <div onClick={() => void 0} role="listitem" /> ``` --- ### jsx-a11y/no-noninteractive-element-to-interactive-role | rules | | | -------- | -------- | | 說明 | 此規則禁止==noninteractive的DOM==被設定成==interactive-role==(請參考下面列舉)| | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1(4.1.2) | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-noninteractive-element-to-interactive-role.md | - Non-interactive ARIA roles 有 `article`, `banner`, `complementary`, `img`, `listitem`, `main`, `region` and `tooltip` - 具有互動性的DOM有: `<a href>`, `<button>`, `<input>`, `<select>`, `<textarea>`. - 無互動的DOM有:`<main>`, `<area>`, `<h1-h6>`, `<img>`, `<li>`, `<ul>` and `<ol>`. ```htmlmixed! // 如果noninteractive的DOM想設定interactive role則需要多包一層來實作 // case 1: <li> <div role="button" onClick={() => {}} onKeyPress={() => {}}> Save </div> </li> // case 2: <div role="button" onClick={() => {}} onKeyPress={() => {}} tabIndex="0"> <img src="some/file.png" alt="Save" /> </div> ``` --- ### jsx-a11y/no-noninteractive-tabindex | rules | | | -------- | -------- | | 說明 | 禁止noninteractive DOM設定tabindex屬性<br>當使用者透過tab導航時,會預期是focus於可互動的元件上| | 對應指引 | 成功準則2.1.1:鍵盤 (檢測等級A) | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-noninteractive-tabindex.md 建議閱讀文件case| > 一般而言,我們要盡可能減少非必要的tabindex設定於網頁上 像是在ul/li中設定只是為了讓閱讀器照順序念出,screen reader本來就可以讀取的到這些內容,這就是一個多餘的設定 ```htmlmixed! <div /> <MyButton tabIndex={0} /> <button /> <button tabIndex="0" /> <button tabIndex={0} /> <div /> <div tabIndex="-1" /> <div role="button" tabIndex="0" /> <div role="article" tabIndex="-1" /> <article tabIndex="-1" /> ``` --- ### jsx-a11y/no-redundant-roles | rules | | | -------- | -------- | | 說明 | 不要設定多餘的roles(不需要說廢話),[HTML語意化標籤有自帶隱含的role](https://www.w3.org/TR/html-aria/#docconformance ),會檢查是否重複設定 | | 對應指引 | General best practice ([reference resources](https://www.w3.org/TR/using-aria/#aria-does-nothing)) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-redundant-roles.md | > 延伸閱讀:[HTML element Implicit ARIA semantics](https://www.w3.org/TR/html-aria/#docconformancehttps://www.w3.org/TR/html-aria/#docconformance) ```htmlmixed! // Succeed <div /> <button role="presentation" /> <MyComponent role="main" /> // Fail <button role="button" /> // 本身是button, 就不用在下 role="button" <img role="img" src="foo.jpg" /> // img, 就不用在下 role="img" <h1 role="heading">heading text</h1> // role="heading" 很多餘 ``` --- ### jsx-a11y/no-static-element-interactions | rules | | | -------- | -------- | | 說明 | 當靜態元素有添加互動事件時( 預設比對`onClick`, `onMouseDown`, `onMouseUp`, `onKeyDown`, `onKeyUp`事件 ),該元素也必須具有role值(可參考下方列表)。 | | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/no-static-element-interactions.md | - [WAI-ARIA 的role屬性](https://www.w3.org/TR/wai-aria-1.1/#usage_intro)為元素提供了語義意涵。這個語義值可以通過輔助技術向用戶表達。 - 靜態 HTML 元素(像是`<div>` 和 `<span>`)沒有語義上的意義。但是,在看似具有語義的元素中(例如 `<a>`、`<big>`、`<blockquote>`、`<footer>`、`<picture>`、`<strike>` 和 `<time>` 等),對於輔助技術中它們與 `<div>` 一樣沒有意義。 **常見的 interactive roles 值有:** 1. button 2. link 3. checkbox 4. menuitem 5. menuitemcheckbox 6. menuitemradio 7. option 8. radio 9. searchbox 10. switch 11. textbox ```htmlmixed! // Succeed <button onClick={() => {}} className="foo" /> <div className="foo" onClick={() => {}} role="button" /> <input type="text" onClick={() => {}} /> // Fail <div onClick={() => {}} /> ``` --- ### jsx-a11y/role-has-required-aria-props | rules | | | -------- | -------- | | 說明 | elememt若有設定role值,會檢核此role必需搭配aria-*值是否有設定 | | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/role-has-required-aria-props.md | ```htmlmixed! // Succeed <!-- Good: the checkbox role requires the aria-checked state --> <span role="checkbox" aria-checked="false" aria-labelledby="foo" tabindex="0"></span> <!-- Bad: the checkbox role requires the aria-checked state --> <span role="checkbox" aria-labelledby="foo" tabindex="0"></span> ``` --- ### jsx-a11y/role-supports-aria-props | rules | | | -------- | -------- | | 說明 | 此規則會檢核element在aria-*值設定上是否使用正確,因為某些role值只支援特定的aria-*值 | | 對應指引 | 成功準則4.1.2:名稱、角色和值 (檢測等級A) | |NCC-APP 識別碼| NT1(4.1.2) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/role-supports-aria-props.md | ```htmlmixed! // Succeed <!-- Good: the radiogroup role does support the aria-required property --> <ul role="radiogroup" aria-required aria-labelledby="foo"> <li tabIndex="-1" role="radio" aria-checked="false">Rainbow Trout</li> <li tabIndex="-1" role="radio" aria-checked="false">Brook Trout</li> <li tabIndex="0" role="radio" aria-checked="true">Lake Trout</li> </ul> // Fail <!-- Bad: the radio role does not support the aria-required property --> <ul role="radiogroup" aria-labelledby="foo"> <li aria-required tabIndex="-1" role="radio" aria-checked="false">Rainbow Trout</li> <li aria-required tabIndex="-1" role="radio" aria-checked="false">Brook Trout</li> <li aria-required tabIndex="0" role="radio" aria-checked="true">Lake Trout</li> </ul> ``` --- ### jsx-a11y/scope | rules | | | -------- | -------- | | 說明 | 只有 `<th>` elements才能設定`scope`屬性 | | 對應指引 | 成功準則1.3.1:資訊與關連性 (檢測等級A)<br>成功準則4.1.1:語法分析 (檢測等級A) | |NCC-APP 識別碼| ST2(4.1.1) | | 文件說明 |https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/scope.md | ```htmlmixed! // Succeed <th scope="col" /> <th scope={scope} /> // Fail <div scope /> ``` --- ### jsx-a11y/tabindex-no-positive | rules | | | -------- | -------- | | 說明 | tabIndex的數值(遞增)必須與網頁的排版順序一致 | | 對應指引 | 成功準則2.4.3:焦點順序 (檢測等級A) | |NCC-APP 識別碼| FC3 | | 文件說明 | https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/HEAD/docs/rules/tabindex-no-positive.md | ```htmlmixed! // Succeed <span tabIndex="0">foo</span> <span tabIndex="-1">bar</span> <span tabIndex={0}>baz</span> // Fail <span tabIndex="5">foo</span> <span tabIndex="3">bar</span> <span tabIndex="1">baz</span> <span tabIndex="2">never really sure what goes after baz</span> ``` --- ## 對應NCC規範與十三指引 ### 不在eslint-plugin-jsx-a11y中的十三指引規範 ==黃底標註為NCC-APP識別碼== 請對照此頁[檢測碼與稽核評量碼](https://accessibility.moda.gov.tw/Accessible/Guide/68)的範例說明 - 指引1.2:時序媒體 - [成功準則1.2.4:字幕(現場直播) (檢測等級AA)](https://accessibility.moda.gov.tw/Download/Detail/1555?Category=64) - [成功準則1.2.5:音訊描述(預錄) (檢測等級AA)](https://accessibility.moda.gov.tw/Download/Detail/1556?Category=64) - 指引1.3:可調適 - 成功準則1.3.2:有意義的序列 (檢測等級A) ==AD1== (內容順序) - 當內容中的呈現順序會影響其意義時,應該要能以程式化的方式,判讀正確的閱讀序列。 - [將內容依據有意義的序列來排序](https://accessibility.moda.gov.tw/Download/Detail/1578?Category=64) - [使用萬國碼的右至左標記(RLM)或左至右標記(LRM)來即席混用文字走向,或在行內組件使用文字方向屬性以解決巢狀文字走向的問題](https://accessibility.moda.gov.tw/Download/Detail/1513?Category=63) - [使用CSS來控制字詞內的字母間距](https://accessibility.moda.gov.tw/Download/Detail/1580?Category=64) - [DOM物件順序需與視覺順序一致](https://accessibility.moda.gov.tw/Download/Detail/1581?Category=64) - [成功準則1.3.3:知覺特徵 (檢測等級A)](https://accessibility.moda.gov.tw/Download/Detail/1582?Category=64) - [成功準則1.3.4:螢幕方向 (檢測等級AA)](https://accessibility.moda.gov.tw/Download/Detail/1583?Category=64) ==AD2== (螢幕方向) - 除非使用特定的顯示方向有其必要性,螢幕內容顯示和操作不應限制為單一顯示方向,例如直向或橫向。 - 指引1.4:可辨識 - 成功準則1.4.1:色彩使用 (檢測等級A) - [確保所有藉由顏色所傳達出來的訊息,在沒有顏色後仍然能夠傳達出來](https://accessibility.moda.gov.tw/Download/Detail/1589?Category=64) - [當使用者介面元件取得焦點時,使用CSS變更其呈現方式](https://accessibility.moda.gov.tw/Download/Detail/1590?Category=64) - [對有顏色的表單控制標題,提供文字線索提示](https://accessibility.moda.gov.tw/Download/Detail/1591?Category=64) - [成功準則1.4.2:音訊控制 (檢測等級A)](https://accessibility.moda.gov.tw/Download/Detail/1592?Category=64) ==AV2== (不得自動播放音訊) - 如果網頁上有任何音訊會自動播放達3秒鐘以上,應提供一套機制來暫停或中止音訊播放,或者要能在整體系統音量設定外,另外提供控制音量的機制。 - 成功準則1.4.3:對比值(最小) (檢測等級AA) ==DT2== (文字對比) - 除非是下列各款中的例外情形,否則文字及影像文字的視覺呈現,至少要有4.5:1的對比值 - 大尺寸的文字及大尺寸的影像文字至少要有3:1的對比值。 - 閒置中的使用介面元件上的、純裝飾用的、任何人都看不到的文字或影像文字,或者只是另一張圖片的局部且該圖片顯然還有其他視覺內容,都毋須要求對比值。 - 標識或商標名稱上的字樣沒有最小對比值的要求。 - 成功準則1.4.4:調整文字尺寸 (檢測等級AA) ==DT3== (調整文字尺寸) 除字幕及影像文字外,文字在沒有額外輔助科技的情況下,要能夠放大至百分之兩百,而不會失去內容或功能性。 - [使用具有支援縮放功能且容易取得的使用者代理的科技,或者在頁面上提供可讓使用者變大所有文字尺寸到百分之兩百為止的控制元件](https://accessibility.moda.gov.tw/Download/Detail/1597?Category=64) - [使用流動版面設計,或者確認當文字尺寸變更而文字容器尺寸並未變更時,不會喪失任何內容或功能](https://accessibility.moda.gov.tw/Download/Detail/1598?Category=64) - [縮放含有文字的表單組件](https://accessibility.moda.gov.tw/Download/Detail/1599?Category=64) - 成功準則1.4.5:影像文字 (檢測等級AA) - 成功準則1.4.10:流動排版 (檢測等級AA) - 成功準則1.4.11:非文字對比 (檢測等級AA) - 成功準則1.4.12:文字間距 (檢測等級AA) - 成功準則1.4.13:懸浮或焦點內容 (檢測等級AA) ==DC3== (懸浮內容) - 附加懸浮內容因指標移動或鍵盤焦點觸發而可視後隱藏時,下列為真: - 可移除:提供一種機制移除附加懸浮內容,不用移動指標或鍵盤焦點,除非是附加懸浮內容傳達輸入錯誤或未隱藏或替換其他內容; - 可移動:如果指標移動可觸發附加懸浮內容,則指標可以在附加懸浮內容上移動而不會使該內容消失; - 持續性:附加懸浮內容應維持可見,直到指標移出或鍵盤焦點移除、使用者解除或資訊不再有效。 - 例外:附加懸浮內容的視覺呈現應由使用者代理控制而非由網頁作者修改。 **Example** - [使懸浮或焦點內容可移除或維持,使其呈現可忽略或持續](https://accessibility.moda.gov.tw/Download/Detail/1634?Category=64) - [於游標無法移動到懸浮的內容,而導致成功準則1.4.13失敗](https://accessibility.moda.gov.tw/Download/Detail/1635?Category=64) - 指引2.1:鍵盤可操作 - [成功準則2.1.2:無鍵盤操作陷阱 (檢測等級A) ](https://accessibility.moda.gov.tw/Download/Detail/1638?Category=64) ==FC2== (鍵盤陷阱) - 如果可以使用鍵盤介面,將鍵盤焦點移至頁面中的某個元件,則也要能僅用鍵盤介面就把焦點移開;如果移開焦點需要用到普通的方向鍵、跳位鍵以外的按鍵,或其他標準的離開方法,則需告知使用者如何操作。 - 成功準則2.1.4:快捷鍵 (檢測等級A) - 指引2.2:充足時間 - 成功準則2.2.1:計時調整 (檢測等級A) ==DC5== (超時) - 對於每一個由內容所設定的時間限制來說,下列各款至少得做到其中一項: - [使用者遇上時間限制之前就能把它關掉。](https://accessibility.moda.gov.tw/Download/Detail/1642?Category=64) - [使用者遇上時間限制之前就能加以調整,而且可調整的範圍要很大,至少是預設設定的10倍以上。](https://accessibility.moda.gov.tw/Download/Detail/1643?Category=64) - 計時截止之前先警告使用者,並保留至少20秒的時間,讓使用者用簡單的動作(例如「按空白鍵」)來延長時限,且使用者至少能延長時限10次以上。 - 當時間限制為即時事件(例如拍賣)中所需要的部份,而且不可能有任何替代的時限時,可不允許計時調整。 - 當時限為必要,且延長時限會使得活動無效時,可不允許計時調整。 - 當時限比20小時還長時,可不允許計時調整。 - 指引2.3:預防痙攣和身體不適反應 - 成功準則2.3.1:閃爍三次或低於閾值 (檢測等級A) ==DC1== (禁止閃爍) - [網頁上不可含有任何一個元件,其在任何1秒鐘之內,會閃爍超過3次,或者閃爍低於一般閃爍以及紅閃爍閾值。](https://accessibility.moda.gov.tw/Download/Detail/1656?Category=64) - 指引2.4:可導覽 - 成功準則2.4.2:網頁標題 (檢測等級A) ==ST1== (單一頁面標題) - [網頁有用標題來描述主旨或目的。](https://accessibility.moda.gov.tw/Download/Detail/1515?Category=63) - [提供網頁的描述性標題。](https://accessibility.moda.gov.tw/Download/Detail/1664?Category=64) - 成功準則2.4.7:焦點可視 (檢測等級AA) - [成功準則2.4.9:鏈結目的(僅鏈結) (檢測等級AAA) ](https://accessibility.moda.gov.tw/Download/Detail/1518?Category=63) ==DT1== (可操作元件) - 每一個鏈結目的應僅由鏈結文字本身即可辨識,除非鏈結目的對整體使用者來說均不明確。 - 指引2.5:輸入方式 - 成功準則2.5.1:指標手勢 (檢測等級A) ==TS1== (單點觸控) - 除非基於多點或基於路徑的手勢有其必要性,所有使用多點或基於路徑的手勢進行的功能性操作,都可以使用單一指標操作而無需使用基於路徑的手勢。 - [提供單點指標控制元件以實現與基於路徑或多點手勢相同的結果](https://accessibility.moda.gov.tw/Download/Detail/1684?Category=64) - [為控制滑塊提供單點啟動](https://accessibility.moda.gov.tw/Download/Detail/1685?Category=64) - 成功準則2.5.2:指標取消 (檢測等級A) ==TS2== (觸發操作) - 對於可以使用單一指標操作的功能,至少須滿足下列條件之一: - 無向下事件:指標的向下事件不被用於執行任何部分的功能; - 中止或取消:該功能的完成在向上事件,並且有一種機制可以在完成之前中止該功能或在完成後取消該功能; - 向上逆轉:向上事件逆轉先前的向下事件之任何結果。 - 必要性:完成向下事件的功能有其必要性。 **Example** - [使用網頁規範原生控制元件來確保在向上事件發生時可觸發功能](https://accessibility.moda.gov.tw/Download/Detail/1688?Category=64) - [確保可以取消拖放操作](https://accessibility.moda.gov.tw/Download/Detail/1687?Category=64) - 成功準則2.5.3:標籤名稱 (檢測等級A) - 成功準則2.5.4:動作啟動 (檢測等級A) - 成功準則2.5.5:目標尺寸 (檢測等級AAA) ==TS3== (觸控目標尺寸) - 針對藉由裝置動作或使用者動作進行操作的功能,也可以採取使用者介面元件操作,並可截斷針對該動作所作出的回應以防止意外的啟動,但以下情況除外: - 支援性介面:該動作用於透過無障礙支援介面來操作功能; - 必要性:該動作對於功能有其必要,且這樣做會使活動失效。 Example - 除以下條件外,指標輸入的目標尺寸至少為44乘44 CSS像素: ● 等效:目標可透過同一網頁上等效的鏈結或控制元件獲得,該目標尺寸至少須為44乘44 CSS像素; ● 行內:指標操作目標位於句子或文字區塊內; ● 使用者代理控制:指標操作目標的外觀是由使用者代理決定而非由網頁作者修改; ● 必要性:指標操作目標特定的呈現方式對於資訊的傳遞有其必要性。 - 指引3.1:可讀性 - 成功準則3.1.2:局部語言 (檢測等級AA) - 指引3.2:可預期性 - [成功準則3.2.1:焦點 (檢測等級A)](https://accessibility.moda.gov.tw/Download/Detail/1706?Category=64) ==FM4== (管理焦點) - 當任何元件獲得焦點時,並不會使前後脈絡產生改變。 - 成功準則3.2.2:輸入 (檢測等級A) - [表單控制元件之行為將使網頁跳轉或變更,則在脈絡變更前需先明確描述將發生的事情](https://accessibility.moda.gov.tw/Download/Detail/1707?Category=64) - [使用按鈕來做出行動並啟動脈絡變更](https://accessibility.moda.gov.tw/Download/Detail/1708?Category=64) - [提供下載檔案格式為不需依賴特定文書商用軟體即能開啟之檔案](https://accessibility.moda.gov.tw/Download/Detail/1709?Category=64) - 成功準則3.2.3:一致的導覽 (檢測等級AA) ==PD2== (一致的導覽) - [除非使用者做出變更,否則在一組網頁中,反覆出現的導覽機制每次都要有相同的相對順序。](https://accessibility.moda.gov.tw/Download/Detail/1710?Category=64) - 成功準則3.2.4:一致的識別 (檢測等級AA) ==PD3== (一致的識別) - [在一組網頁中,具有相同功能性的元件,就要有一致的識別。](https://accessibility.moda.gov.tw/Download/Detail/1711?Category=64) - 指引3.3:輸入協助 - 成功準則3.3.1:識別錯誤 (檢測等級A) - 成功準則3.3.3:錯誤建議 (檢測等級AA) ==NT2== (錯誤訊息和更正) - 如果輸入的錯誤能夠自動地偵測出來,而且已知更正的建議,除非會危及安全性或內容的目的,否則就向使用者提供建議。 - **Example1:** [提供文字描述以指明未完成的必填欄位,並建立可以讓使用者跳到出錯之處的機制](https://accessibility.moda.gov.tw/Download/Detail/1724?Category=64) - **Example2:** [使用者輸入的內容不在允許清單中,或格式未符合所需時,均提供文字描述,並提供建議的文字校正](https://accessibility.moda.gov.tw/Download/Detail/1725?Category=64) - 成功準則3.3.4:錯誤預防(法律、財務、個人資料) (檢測等級AA) - 指引4.1:相容性 - 成功準則4.1.3:狀態訊息 (檢測等級AA) ---