ARIA:radio 角色
radio 角色是一組可選單選按鈕中的一部分,位於 radiogroup 中,一次只能選中一個單選按鈕。
描述
單選按鈕是一個可選輸入,當與其他單選按鈕關聯時,一次只能選中其中一個。單選按鈕必須在 radiogroup 中組合在一起,以指示哪些按鈕影響相同的值。
<div role="radiogroup" aria-labelledby="legend25" id="radiogroup25">
<p id="legend25">Ipsum and lorem?</p>
<div>
<span
role="radio"
aria-checked="false"
tabindex="0"
aria-labelledby="q25_radio1-label"
data-value="True"></span>
<label id="q25_radio1-label">True</label>
</div>
<div>
<span
role="radio"
aria-checked="false"
tabindex="0"
aria-labelledby="q25_radio2-label"
data-value="False"></span>
<label id="q25_radio2-label">False</label>
</div>
<div>
<span
role="radio"
aria-checked="true"
tabindex="0"
aria-labelledby="q25_radio3-label"
data-value="huh?"></span>
<label id="q25_radio3-label">What is the question?</label>
</div>
</div>
role 屬性僅新增語義;HTML 單選按鈕 本身附帶的所有功能都需要使用 JavaScript 和 HTML tabindex 屬性新增。
注意:ARIA 的第一條規則是,如果本機 HTML 元素或屬性具有您所需的功能和行為,請使用它,而不是重新利用元素並新增 ARIA。而是使用本機 HTML <input type="radio">(以及關聯的 <label>),它本身提供了所有必需的功能
<fieldset>
<legend>Ipsum and lorem?</legend>
<div>
<input type="radio" value="True" id="q25_radio1" name="q25" />
<label for="q25_radio1">True</label>
</div>
<div>
<input type="radio" value="False" id="q25_radio2" name="q25" />
<label for="q25_radio2">False</label>
</div>
<div>
<input type="radio" value="huh?" id="q25_radio3" name="q25" checked />
<label for="q25_radio3">What is the question?</label>
</div>
</fieldset>
本機 HTML 單選表單控制元件 (<input type="radio">) 有兩種狀態(“選中”或“未選中”)。類似地,具有 role="radio" 的元素可以透過 aria-checked 屬性公開兩種狀態:true 表示選中狀態,false 表示未選中狀態。對於單選按鈕,aria-checked 值 mixed 無效。
如果選中了單選按鈕,則單選按鈕元素的 aria-checked 設定為 true。如果未選中,則其 aria-checked 設定為 false。
每個單選按鈕元素都具有角色 radio。radio 角色應始終巢狀在 radiogroup 中的其他關聯 radio 中。如果無法將單選按鈕巢狀在 radio 組中,請在 radiogroup 元素的 aria-owns 屬性的值中使用非分組 radio 的 id 作為以空格分隔的值列表,以指示 radiogroup 與其 radio 成員的關係。
每個 radio 元素都由其內容標記,具有 aria-labelledby 引用的可見標籤,或使用 aria-label 指定的標籤。包含的 radiogroup 元素應具有 aria-labelledby 引用的可見標籤或使用 aria-label 指定的標籤。如果存在提供有關 radio 組或每個 radio 按鈕的其他資訊的元素,則這些元素應由 radiogroup 元素或使用 aria-describedby 屬性的 radio 元素引用。
由於 radio 是一個互動式控制元件;它必須可聚焦且可透過鍵盤訪問。如果角色應用於不可聚焦的元素,請使用 tabindex 屬性更改此設定。啟用 radio 的預期鍵盤快捷鍵是 空格鍵。使用 JavaScript 將 aria-checked 屬性切換到 true,當 radio 被選中時,同時確保該組中的所有其他 radio 角色都設定為 aria-checked="false"。
要以程式設計方式指示必須從 radio 組中選擇單選按鈕,必須在 radiogroup 元素上指定 aria-required 屬性(值為 true)。不建議在單個 ARIA 單選按鈕上使用 aria-required 屬性。
所有後代都是表示性的
某些型別的使用者介面元件在平臺輔助功能 API 中表示時,只能包含文字。輔助功能 API 沒有方法表示包含在 radio 中的語義元素。為了解決此限制,瀏覽器會自動將角色 presentation 應用於任何 radio 元素的所有後代元素,因為它是一個不支援語義子元素的角色。
例如,考慮以下 radio 元素,其中包含一個標題。
<div role="radio"><h6>name of my radio</h6></div>
由於 radio 的後代是表示性的,因此以下程式碼等效
<div role="radio"><h6 role="presentation">name of my radio</h6></div>
從輔助技術使用者的角度來看,標題不存在,因為前面的程式碼片段在 輔助功能樹 中等效於以下內容
<div role="radio">name of my radio</div>
關聯的 WAI-ARIA 角色、狀態和屬性
radiogroup角色-
單選按鈕包含在或屬於具有
radiogroup角色的元素中。如果無法在標記中巢狀在radiogroup內,則radiogroup的aria-owns屬性包含組中未巢狀的單選按鈕的id值。 aria-checked-
aria-checked的值定義了單選按鈕的狀態。當與單選按鈕元素一起使用時,該屬性具有兩個可能的值之一
注意:如果在預設情況下不接受鍵盤焦點的元素(例如,<div> 或 <span>)上使用 role="radio",請使用 tabindex 屬性。
鍵盤互動
- Tab + Shift
-
將焦點移入和移出單選按鈕組。當焦點移入單選按鈕組時,如果某個單選按鈕已被選中,則焦點將設定在選中的按鈕上。如果沒有任何單選按鈕被選中,則焦點將設定在組中的第一個單選按鈕上。
- 空格鍵
-
如果單選按鈕未被選中,則選中它。取消選中單選按鈕組中先前選中的單選按鈕。
- 右箭頭 和 下箭頭
-
將焦點移動到組中的下一個單選按鈕並選中它,同時取消選中先前獲得焦點的單選按鈕。如果焦點位於最後一個單選按鈕上,則焦點將移動到第一個單選按鈕。
- 左箭頭 和 上箭頭
-
將焦點移動到組中的上一個單選按鈕並選中它,同時取消選中先前獲得焦點的單選按鈕。如果焦點位於第一個單選按鈕上,則焦點將移動到最後一個單選按鈕。
工具欄中的單選按鈕
由於箭頭鍵用於在工具欄元素之間導航,並且 Tab 鍵用於將焦點移入和移出工具欄,因此當單選按鈕組巢狀在工具欄中時,單選按鈕組的鍵盤互動方式略有不同於不在工具欄內的單選按鈕組。有關更多資訊,請參閱 radiogroup 鍵盤互動。
必需的 JavaScript
onClick-
處理單選按鈕和關聯標籤上的滑鼠點選,這將透過更改
aria-checked屬性的值以及單選按鈕的外觀(使其對視力正常的使用者顯示為選中或未選中)來更改單選按鈕的狀態。 onKeyPress-
處理使用者按下 空格鍵 以更改單選按鈕狀態的情況,這將透過更改
aria-checked屬性的值以及單選按鈕的外觀(使其對視力正常的使用者顯示為選中或未選中)來更改單選按鈕的狀態。
示例
以下示例使用 ARIA 將其他通用元素修改為單選按鈕。CSS 和 JavaScript 用於視覺上和程式設計方式地修改元素的選中或未選中狀態。
HTML
<div role="radiogroup" aria-labelledby="legend" id="radiogroup">
<p id="legend">
Should you be using the <code>radio</code> role or
<code><input type="radio"></code>?
</p>
<div>
<span
role="radio"
aria-checked="true"
tabindex="0"
aria-labelledby="ariaLabel"
data-value="True"></span>
<label id="ariaLabel">ARIA role</label>
</div>
<div>
<span
role="radio"
aria-checked="false"
tabindex="0"
aria-labelledby="htmllabel"
data-value="False"></span>
<label id="htmllabel">HTML <code><input type="radio"></code></label>
</div>
</div>
CSS
[role="radio"] {
padding: 5px;
}
[role="radio"][aria-checked="true"]::before {
content: "(x)";
font-family: monospace;
}
[role="radio"][aria-checked="false"]::before {
content: "( )";
font-family: monospace;
}
JavaScript
需要大量的 JavaScript 程式碼才能將非語義 HTML 元素轉換為單選按鈕。
// initialize all the radio role elements
const radioGroups = document.querySelectorAll('[role="radiogroup"]');
for (let i = 0, groups = radioGroups.length; i < groups; i++) {
const radios = radioGroups[i].querySelectorAll("[role=radio]");
for (let j = 0, radiobuttons = radios.length; j < radios; j++) {
radios[j].addEventListener("keydown", function () {
handleKeydown();
});
radios[j].addEventListener("click", function () {
handleClick();
});
}
}
// handle mouse and touch events
let handleClick = function (event) {
setChecked(this);
event.stopPropagation();
event.preventDefault();
};
// handle key presses
let handleKeydown = function (event) {
switch (event.code) {
case "Space":
case "Enter":
currentChecked();
break;
case "ArrowUp":
case "ArrowLeft":
previousRadioChecked();
break;
case "ArrowDown":
case "ArrowRight":
nextItemChecked();
break;
default:
break;
}
event.stopPropagation();
event.preventDefault();
};
// when a radio is selected, give it focus, set checked to true;
// ensure all other radios in radio group are not checked
setChecked = function () {
// uncheck all the radios in group
// iterated through all the radios in radio group
// eachRadio.tabIndex = -1;
// eachRadio.setAttribute('aria-checked', 'false');
// set the selected radio to checked
// thisRadio.setAttribute('aria-checked', 'true');
// thisRadio.tabIndex = 0;
// thisRadio.focus();
// set the value of the radioGroup to the value of the currently selected radio
};
如果我們使用語義 HTML 元素,並且一組單選按鈕中每個單選按鈕的名稱都相同,則不需要 JavaScript(甚至 CSS)。
<fieldset>
<legend>
Should you be using the <code>radio</code> role or
<code><input type="radio"></code>?
</legend>
<div>
<input type="radio" name="bestPractices" id="ariaLabel" value="True" />
<label for="ariaLabel">ARIA role</label>
</div>
<div>
<input type="radio" name="bestPractices" id="htmllabel" value="False" />
<label for="htmllabel">HTML <code><input type="radio"></code></label>
</div>
</fieldset>
最佳實踐
ARIA 的第一條規則是:如果本機 HTML 元素或屬性具有您所需的語義和行為,請使用它,而不是重新利用元素並新增 ARIA 角色、狀態或屬性使其可訪問。因此,建議使用本機 HTML 單選按鈕 表單控制元件,而不是使用 JavaScript 和 ARIA 重新建立單選按鈕的功能。