Zenn
🧑‍🍼

HTMLとWAI-ARIAについてのまとめと気を付けるポイントメモ

2025/02/18に公開
1


WAI-ARIAについては何となく存在を知っていましたが、その程度の知識しかありませんでした。もう少しきちんと知識を整理して対応していこうと思い、個人的な対応方針を決定するまでの情報整理や思考した軌跡と結論を備忘メモとして残しておきます。
この記事に書かれている内容は個人の解釈・主観が多分に含まれていることに加えて情報の行間等も全てを記せていません。情報を整理している中で、私が認識したためその時に気を付ければいいか、と思い記載していない内容等もあります。解釈が誤っている可能性もあるため、全体像をある程度把握するための参考程度にすることをおすすめします。

WAI-ARIAについて

概要

HTML文書等で著者の意図する以下のような内容を論理的に解釈可能とするための情報を付与した文書。意図を論理的に解釈可能とすることでスクリーンリーダー等の他ソフトウェアが文書をより適切に取り扱うことが可能になる。

  • 意味的な文書構造
  • 文章の構成
  • 対話的文脈の操作性
  • コンテンツの動的な状態

これを実現するためWAI-ARIA RoleやWAI-ARIA States and Propertiesといった仕様に加えて、HTML文書等のマークアップ定義に高い親和性を持つための追加的な仕様が設けられた。具体的には特別な情報を付与しない場合でも特定のHTMLタグ等の要素には特定のRoleが内包されていると見なしたり、要素の属性として追加的に情報を付与可能であることなど。仕様では適切な文書要素を使用することで意図を論理的に解釈可能とすべきで追加的な情報付与はしないことが望ましく、必要になった場合にのみ追加的に情報を付与するという方針となっている。これは裏を返せば、WAI-ARIAを用いてアクセシビリティ対応をするためには各要素が標準で何を意味するのかを網羅的に把握し、文書著者が情報を追加付与する条件を理解しなければならないということになる。

対応は必要か

法改正によりコンプライアンス的に負担が重すぎない範囲で対応が必要となった[1]ため、プロジェクトにより対応内容の決定が必要。「他のソフトウェア」は典型的にはOS,ブラウザ,スクリーンリーダーが挙げられるがそれ以外に無いと断定することはできないし、ターゲットユーザーとそれに関する「他のソフトウェア」は無数にあるためどこまでをスコープに含めるのかを先に検討する必要がある。

前提

この記事について

  • WAI-ARIAを用いてアクセシビリティ対応を行うことを目的とする
  • WAI-ARIA適用先文書はHTML文書と定義する
  • WAI-ARIA1.3のドラフト文書とARIA in HTMLのドラフト文書がベース
    • 日本語版MDNは内容が異なる(誤っている?)場合がある (英語版は一致していたりする)
    • ARIA in HTMLとこの記事の内容が異なる場合がある
      • ARIA in HTMLの記載に違和感があった場合のみ個別に検証して内容を置換
        • 検証はChromeブラウザで実施
        • 例) markタグやdtタグの暗黙のARIAロール
  • この辺この辺程度の知識がある前提
  • Accessible Nameについても知っている前提
  • Deprecatedとなっている項目には対応していない
  • "WAI-ARIA Role"は「ロール」、"WAI-ARIA States and Properties"はまとめて「プロパティ」と表記する
  • HTMLタグのことを単にタグと表記する場合がある
  • "presentation"ロールは取り扱わず"none"ロールのみ取り扱う
  • "img"ロールは"image"ロールと表記する
  • "暗黙のARIAロール"は暗黙ロールと表記する
  • 文書構造における構造概要を把握するための指針となる区域をランドマーク(Landmark)と表記する
  • h1-h6タグはh0と表記する
  • inputタグのようなユーザーが操作可能な要素を対話的要素と表記する
  • 空要素は<tag />のように表記する

目標

WAI-ARIAを用いて最小労力である程度のアクセシビリティを担保したページを作成できるようになる。

  • できる限り覚えることを減らし認知負荷を軽減する
  • 特定用途は認識だけして覚えず、その時に詳細を調べることにする
    • 何が特定用途かは主観によって決めた
    • 特定用途の内容の全てを記載しているわけではない
  • できるだけ正確な理解と使用を心がけつつ、問題なさそうな部分は極力省く

基本方針

  • 可能な限り標準のHTMLで表現する
    • 対話的要素はHTML標準の要素を用いる
    • 要素の親子関係表現はHTML階層を用いる
    • 要素を列挙する場合は列挙と内容で構造を分離する
  • 適切なHTMLタグを用いれば考慮しなくてよい制約等は考慮しない
    • 状況に応じて適切なHTMLタグを使用するようにする
  • 各HTMLタグの用途を自ら制限し、タグとロールの紐付けを強くする
    • 情報を付与する条件を簡略化して認知負荷を下げる
    • 紐付けによりロールとタグの各制約を整合性を保ちつつ統合・簡略化するため
  • HTMLタグに付与された暗黙ロールを尊重する
    • 言い換えると特に必要でない限りHTMLタグにrole属性を使用しない
  • 特定タグにわざわざrole="none"を付与して使用せず素のdiv,spanを使用する
    • どうしても特定タグを使用する理由がある場合はこの限りでない
  • 以下例等は特定用途と見なして考慮外とする
    • 動的テーブル,grid系,tree系ロール
    • live-regionの詳細設定

暗黙ロールの尊重について

以下のような例の場合でも暗黙ロールを尊重する。

  • "generic"ロールは使用すべきでないとされている

    Authors SHOULD NOT use this role in content.
    (generic role)

  • しかしbodyタグやdivタグ等暗黙ロールに"generic"が割り当てられている
  • わざわざrole="none"とする方が冗長な情報付与となるため、指定しないことにする
    • なぜ"No correspoinding role"にしなかったのかは謎

タグとロール紐付け

ロール間の関係性

ロールにはHTMLタグに指定できない抽象ロール(Abstract Role)とそれ以外のロール(この記事では以下 具象ロール)がある。抽象ロール間の対応と具象ロールの関係性の表は以下。複数の具象ロールから多重継承している具象ロールはどちらか片方の親からしか派生していないような表になっている(省いている)。

  • Abstract Roleは(role)で記載
  • 1が上位で4が下位の抽象層
    • 上位抽象層に記載がない場合はその行より上の行の抽象ロールと同じ
      • 例) "(range)"抽象ロールは"(structure)"抽象ロールから派生
    • 下位抽象層に記載がない場合はその層に抽象ロールが無い
      • 例) "generic"ロールは"(structure)"抽象ロールから派生
  • 具象ロールから具象ロールへの継承は親ロールの下の行に>から始まるように記載
    • 例) "article"ロールは"document"ロールから派生
    • 例) "comment"ロールは"article"ロールから派生
Table of role inheritance
1 2 3 4 具象ロール
(roletype) (structure) document
> article
>> comment
generic
none
rowgroup
separator
application
(range) meter
progressbar
scrollbar
(slider)
(spinbutton)
(sectionhead) columnheader
heading
rowheader
tab
(section) alert
> alertdialog
blockquote
caption
cell
code
definition
deletion
emphasis
figure
group
> toolbar
> (select)
image
insertion
list
> feed
listitem
> treeitem
log
mark
marquee
math
note
paragraph
status
> timer
strong
subscript
suggestion
superscript
table
tabpanel
term
time
tooltip
(landmark) banner
complementary
contentinfo
form
main
navigation
region
search
(widget) gridcell
row
(progressbar)
(scrollbar)
(separator)
(tab)
(input) checkbox
> switch
combobox
option
radio
slider
spinbutton
textbox
> searchbox
(command) button
link
menuitem
> menuitemcheckbox
> menuitemradio
(composite) grid
> treegrid
tablist
(spinbutton)
(select) listbox
menu
> menubar
radiogroup
tree
(window) dialog

ロール間の親子制約

  • -は特に制約がない事を表す
  • ,は "または" の意
  • role1/role2のような表記は以下を表す
    • role1ロールの直下にrole2ロールがある
ロール
table caption, row, rowgroup/row -
grid caption, row, rowgroup/row -
treegrid caption, row, rowgroup/row -
caption - figure, group, radiogroup, table, grid, treegrid
rowgroup row table, grid, treegrid
row - table, grid, treegrid, rowgroup
columnheader - row
rowheader - row
cell - row
gridcell - row
menu menuitem, group/menuitem, separator -
menubar menuitem, group/menuitem, separator -
menuitem - menu, menubar, menu/group, menubar/group
list listitem -
listitem - list
tree treeitem, group/treeitem -
treeitem - tree, treeitem/group
tablist tab -
tab - tablist
tabpanel - -
suggestion insertion, deletion -
insertion - -
deletion - -
feed article -
article - -
listbox option, group/option -
option - listbox, listbox/group

似たようなロールの違い

  • グルーピング
    • region: その他のランドマークとなる区域
    • group: ランドマークにならない対話的要素のグルーピング
  • 追加的な情報
    • note: 著者の追加的・補助的な内容
    • comment: 閲覧者の内容・コメントへの反応
    • suggestion: 閲覧者の内容の変更提案1件
  • 操作バー
    • menubar: デスクトップUIで見られるようなメニューバー
    • toolbar: 機能ボタン等の集まりをコンパクトな形式で表現したもの
  • 選択式入力
    • combobox: 入力+選択可能なフォームコントロール
    • listbox: 選択肢から1つ以上の項目を選択できるコントロール
  • リスト
    • menu: コンテキストメニュー等のアクションリスト
    • list: listitem要素を含む区域
  • 情報表示
    • log: 情報蓄積型の静的区域で情報が追加されていくチャット,エラーログ等
    • marquee: 情報移動型の動的区域で情報が上書きされていく株価スクロール表示等
  • 重要度の高い通知
    • alert: ユーザーの操作を必要としない通知区域
    • alertdialog: ユーザーの操作を必要とする通知
  • 表形式
    • table: 対話的な操作が不可能な表形式の表示
    • grid: 対話的な操作が可能な表形式の表示

使用しないロール

以下の具象ロールは一部を除きこの記事では取り扱わない。

  1. application
    • 可能な限り標準のHTMLで表現することが基本方針のため

    • ロール定義

      A structure containing one or more focusable elements requiring user input, such as keyboard or gesture events, that do not follow a standard interaction pattern supported by a widget role.
      (application role)

    • MDNの記載

      このロールは、とても動的でデスクトップ的なウェブアプリケーションを定義するためにのみ使用するべきです。

      このモードでは、ウェブ作成者は、キーボード入力、フォーカス管理、その他のインタラクションを全て処理する責任があり、支援技術が最終的に何らかの処理を行うとは想定できません。
      (ARIA: application ロール)

  2. scrollbar
    • ブラウザのスクロールバーを絶対に使用できない状況が通常想定できないため
    • MDNの記載

      It is always best to use native scroll bars.
      (ARIA: scrollbar role)

  3. menuitemcheckbox
    • 列挙と内容で構造を分離すれば不要なロールと思われるため
  4. menuitemradio
    • 列挙と内容で構造を分離すれば不要なロールと思われるため

タグの基本情報

  • Interface列の表記
    • HTMLElement-と表記
    • 先頭のHTMLと末尾のElementは省略
  • 空列がoとなっているタグは空要素
  • カテゴリ列は代表的なカテゴリのみ記載
HTML tag list
タグ Interface カテゴリ
html Html - head, body -
head Head html title, Metadata -
base Base o head - Metadata
link Link o Metadata - Metadata
meta Meta o head - Metadata
style Style Metadata "text/css" Metadata
title Title head "text" Metadata
body Body html Flow -
address - Flow Flow Flow, Palpable
article - Flow Flow Flow, Sectioning, Palpable
aside - Flow Flow Flow, Sectioning, Palpable
footer - Flow Flow Flow, Palpable
header - Flow Flow Flow, Palpable
h0 Heading Flow Phrasing Flow, Heading, Palpable
hgroup - Flow h0, p Flow, Heading, Palpable
main - Flow Flow Flow, Palpable
nav - Flow Flow Flow, Sectioning, Palpable
section - Flow Flow Flow, Sectioning, Palpable
search - Flow Flow Flow, Palpable
blockquote Quote Flow Flow Flow, Sectioning root, Palpable
dd - dl Flow -
div Div Flow Flow Flow, Palpable
dl DList Flow dt, dd, div Flow
dt - dl Flow -
figcaption - figure Flow -
figure - Flow figcaption, Flow Flow, Palpable
hr HR o Flow - Flow
li LI ul, ol, menu Flow -
menu Menu Flow li, script, template Flow, Palpable
ol OList Flow li, script, template Flow, Palpable
ul UList Flow li, script, template Flow, Palpable
p Paragraph Flow Phrasing Flow, Palpable
pre Pre Flow Phrasing Flow, Palpable
a Anchor Flow Transparent Flow, Phrasing, Interactive, Palpable
abbr - Phrasing Phrasing Flow, Phrasing, Palpable
b - Phrasing Phrasing Flow, Phrasing, Palpable
bdi - Phrasing Phrasing Flow, Phrasing, Palpable
bdo - Phrasing Phrasing Flow, Phrasing, Palpable
br BR o Phrasing - Flow, Phrasing
cite - Phrasing Phrasing Flow, Phrasing, Palpable
code - Phrasing Phrasing Flow, Phrasing, Palpable
data Data Phrasing Phrasing Flow, Phrasing, Palpable
dfn - Phrasing Phrasing Flow, Phrasing, Palpable
em - Phrasing Phrasing Flow, Phrasing, Palpable
i - Phrasing Phrasing Flow, Phrasing, Palpable
kbd - Phrasing Phrasing Flow, Phrasing, Palpable
mark - Phrasing Phrasing Flow, Phrasing, Palpable
q Quote Phrasing Phrasing Flow, Phrasing, Palpable
rp - ruby "text" -
rt - ruby Phrasing -
ruby - Phrasing Phrasing Flow, Phrasing, Palpable
s - Phrasing Phrasing Flow, Phrasing
samp - Phrasing Phrasing Flow, Phrasing, Palpable
small - Phrasing Phrasing Flow, Phrasing, Palpable
span Span Phrasing Phrasing Flow, Phrasing, Palpable
strong - Phrasing Phrasing Flow, Phrasing, Palpable
sub - Phrasing Phrasing Flow, Phrasing, Palpable
sup - Phrasing Phrasing Flow, Phrasing, Palpable
time Time Phrasing Phrasing Flow, Phrasing, Palpable
u - Phrasing Phrasing Flow, Phrasing, Palpable
var - Phrasing Phrasing Flow, Phrasing, Palpable
wbr - o Phrasing - Flow, Phrasing
area Area o map, Phrasing - Flow, Phrasing
audio Audio Embedded source, track, Transparent Flow, Phrasing, Embedded(, Interactive, Palpable)
img Image o Embedded - Flow, Phrasing, Embedded, Palpable
map Map Phrasing Transparent Flow, Phrasing, Palpable
track Track o audio, video - -
video Video Embedded source, track, Transparent Flow, Phrasing, Embedded(, Interactive, Palpable)
embed Embed o Embedded - Flow, Phrasing, Embedded, Interactive, Palpable
fencedframe FencedFrame Embedded - Flow, Phrasing, Embedded, Interactive, Palpable
iframe IFrame Embedded - Flow, Phrasing, Embedded, Interactive, Palpable
object Object Embedded Transparent Flow, Phrasing, Embedded, Palpable
picture Picture Embedded source, img Flow, Phrasing, Embedded
source Source o audio, video, picture - -
svg SVGElement - - -
math - - -
canvas Canvas Phrasing Transparent Flow, Phrasing, Embedded, Palpable
noscript - head, Flow link, style, meta Metadata, Flow, Phrasing
script Script Metadata, Phrasing "text/javascript" Metadata, Flow, Phrasing
del Mod Phrasing Transparent Flow, Phrasing, Palpable
ins Mod Phrasing Transparent Flow, Phrasing, Palpable
caption TableCaption table Flow -
col TableCol o colgroup - -
colgroup TableCol table col -
table Table Flow caption, colgroup, thead, tbody, tr, tfoot Flow
tbody TableSection table tr -
td TableCell tr Flow Sectioning root
tfoot TableSection table tr -
th TableCell tr Flow -
thead TableSection table tr -
tr TableRow table, thead, tbody, tfoot td, th -
details Details Flow summary, Flow Flow, Sectioning root, Interactive, Palpable
dialog Dialog Flow Flow Flow, Sectioning root
summary - details Phrasing, Heading -
slot Slot Phrasing Transparent Flow, Phrasing
template Template Metadata, Phrasing, Script-supporting ANY Metadata, Flow, Phrasing, Script-supporting
button Button Phrasing Phrasing Flow, Phrasing, Interactive, Form-assosciated, Palpable
datalist DataList Phrasing option, Phrasing Flow, Phrasing
fieldset FieldSet Flow legend, Flow Flow, Sectioning root, Form-assosciated, Palpable
form Form Flow Flow Flow, Palpable
label Label Phrasing Phrasing Flow, Phrasing, Interactive, Form-assosciated, Palpable
legend Legend fieldset Phrasing, Heading -
meter Meter Phrasing Phrasing Flow, Phrasing, Palpable
optgroup OptGroup select option -
option Option select, optgroup, datalist "text" -
output Output Phrasing Phrasing Flow, Phrasing, Interactive, Form-assosciated, Palpable
progress Progress Phrasing Phrasing Flow, Phrasing, Palpable
select Select Phrasing option, optgroup, hr Flow, Phrasing, Interactive, Form-assosciated, Palpable
textarea TextArea Phrasing "text" Flow, Phrasing, Interactive, Form-assosciated, Palpable
input Input o Phrasing - Flow, Phrasing, Interactive, Form-assosciated, Palpable

タグに設定されたロール

  • 暗黙ロールの"No corresponding role"は"-"と表記
  • 設定可能なロールが無い場合は"-"と表記
  • ,は "または" の意
  • "*"等が付いている部分は別記条件の場合
  • type属性が"xxx"であるinputタグをinput [xxx]と表記
Role of implicit and available on HTML tag
タグ 暗黙ロール 設定可能ロール 条件
html document -
head - -
base - -
link - -
meta - -
style - -
title - -
body generic -
address group ANY
article article none, application, document, feed, main, region
aside complementary none, feed, note, region, search
footer contentinfo (generic *) none, group * article, aside, main, nav, sectionの各要素、又はroleがarticle, complementary, main, navigation, regionの要素の子孫である場合
header banner (generic *) none, group * article, aside, main, nav, sectionの各要素、又はroleがarticle, complementary, main, navigation, regionの要素の子孫である場合
h0 heading none, tab
hgroup group ANY
main main -
nav navigation none, menu, menubar, tablist
section region (generic *) none, alert, alertdialog, application, banner, complementary, contentinfo, dialog, document, feed, group, log, main, marquee, navigation, note, search, status, tabpanel * accessible nameを持たない場合
search search none, form, group, region
blockquote blockquote ANY
dd definition -
div generic ANY (none *) * dl要素の直下にある時
dl - none, group, list
dt term listitem
figcaption - none, group
figure figure - (ANY *) * 子孫にfigcaption要素がない場合
hr separator none
li listitem none, menuitem, menuitemcheckbox, menuitemradio, option, radio, separator, tab, treeitem (- *) * 親のroleがlistの場合
menu list none, group, listbox, menu, menubar, radiogroup, tablist, toolbar, tree
ol list none, group, listbox, menu, menubar, radiogroup, tablist, toolbar, tree
ul list none, group, listbox, menu, menubar, radiogroup, tablist, toolbar, tree
p paragraph ANY
pre generic ANY
a link (generic *) button, checkbox, menuitem, menuitemcheckbox, menuitemradio, option, radio, switch, tab, treeitem (ANY *) * href属性がない場合
abbr - ANY
b generic ANY
bdi generic ANY
bdo generic ANY
br - none
cite - ANY
code code ANY
data generic ANY
dfn term ANY
em emphasis ANY
i generic ANY
kbd - ANY
mark mark ANY
q generic ANY
rp - ANY
rt - ANY
ruby - ANY
s deletion ANY
samp generic ANY
small generic ANY
span generic ANY
strong strong ANY
sub subscript ANY
sup superscript ANY
time time ANY
u generic ANY
var - ANY
wbr - none
area link (generic *) - (button, link *) * href属性がない場合
audio - application
img image (none *1) button, checkbox, link, math, menuitem, menuitemcheckbox, menuitemradio, meter, option, progressbar, radio, scrollbar, separator, slider, switch, tab, treeitem (- *1, *2) *1 空のalt属性がある場合; *2 alt属性がない場合
map - -
track - -
video - application
embed - none, application, document, image
fencedframe - none, application, document, image
iframe - none, application, document, image
object - none, application, document, image
picture - -
source - -
svg graphics-document ANY
math math -
canvas - ANY
noscript - -
script - -
del deletion ANY
ins insertion ANY
caption caption -
col - -
colgroup - -
table table ANY
tbody rowgroup ANY
td cell (gridcell *1; - *2) - (ANY *2) *1 親のtableのroleがgrid又はtreegridである場合; *2 親のtableのroleがtable, grid, treegridのいずれでもない場合
tfoot rowgroup ANY
th columnheader, rowheader, cell (columnheader, rowheader, gridcell *1; - *2) - (ANY *2) *1 親のtableのroleがgrid又はtreegridである場合; *2 親のtableのroleがtable, grid, treegridのいずれでもない場合
thead rowgroup ANY
tr row - (ANY *) * 親のtableのroleがtable, grid, treegridのいずれでもない場合
details group -
dialog dialog alertdialog
summary - -
slot - -
template - -
button button checkbox, combobox, gridcell, link, menuitem, menuitemcheckbox, menuitemradio, option, radio, separator, slider, switch, tab, treeitem
datalist listbox -
fieldset group none, radiogroup
form form none, search
label - -
legend - -
meter meter -
optgroup group -
option option -
output status ANY
progress progressbar -
select combobox (listbox *) menu (- *) * multiple属性がある又は1よりも大きいsize属性がある場合
textarea textbox -
input [button] button checkbox, combobox, gridcell, link, menuitem, menuitemcheckbox, menuitemradio, option, radio, separator, slider, switch, tab, treeitem
input [checkbox] checkbox menuitemcheckbox, option, switch (button *) * aria-pressed属性を使用する場合
input [color] - -
input [date] - -
input [datetime-local] - -
input [email] textbox (combobox *) - * list属性がある場合
input [file] - -
input [hidden] - -
input [image] button -
input [month] - -
input [number] spinbutton -
input [password] - -
input [radio] radio menuitemradio
input [range] slider -
input [reset] button -
input [search] searchbox (combobox *) - * list属性がある場合
input [submit] button -
input [tel] textbox (combobox *) - * list属性がある場合
input [text] textbox (combobox *) - * list属性がある場合
input [time] - -
input [url] textbox (combobox *) - * list属性がある場合
input [week] - -

selectタグがcomboboxロールである理由

込み入った部分なので複数のAIの回答を比較・参考にした。(DeepSeekは簡潔な回答だったため割愛) 結論はブラウザがうまく対応しているため問題ない。逆に言うと標準のselectタグを使用しない場合は細かな部分に配慮しながら適切に処置する必要があることになる。

  • 質問

通常、selectタグはoptionタグと共に用いてセレクトボックスを表現すると思います。wai-ariaでは、selectタグは属性に何も指定しない場合、comboboxロールになります。optionタグは何も指定しない場合optionロールになりますが、optionロールの定義内に記載のあるRequired Accessibility Parent Rolesは、listbox又はgroup with parent listboxとなっています。これは実体と矛盾しているように思えるのですが、どのように理解すべきでしょうか?

Claude 3.5 Sonnet

ご指摘の点について、WAI-ARIAとHTML標準の関係性から説明させていただきます。

実は、HTMLの<select>要素は2つの異なるARIAセマンティクスを持っています:

  1. 単一選択の場合(multiple属性なし):
  • デフォルトではrole="combobox"role="listbox"の両方の特性を持ちます
  • これは<select>が閉じた状態ではcomboboxとして、開いた状態ではlistboxとして振る舞うためです
  1. 複数選択の場合(multiple属性あり):
  • デフォルトでrole="listbox"となります

つまり、単一選択の<select>要素は以下のような二重の役割を持っています:

<!-- 以下のような <select> は -->
<select>
  <option>選択肢1</option>
  <option>選択肢2</option>
</select>

<!-- 内部的には以下のような構造として解釈されます -->
<div role="combobox">
  <div role="listbox">
    <div role="option">選択肢1</div>
    <div role="option">選択肢2</div>
  </div>
</div>

したがって、<option>要素のRequired Accessibility Parent Rolesがlistboxとなっているのは、この内部構造を反映したものです。見た目上は矛盾しているように見えますが、実際には:

  1. <select>はcomboboxとしての外部インターフェース
  2. その内部にlistboxとしての選択肢コンテナ
  3. さらにその中に個々のoption

という階層構造になっているということです。

この設計により、スクリーンリーダーなどの支援技術は:

  • 閉じている状態ではcomboboxとして(「プルダウンメニューがあります」など)
  • 開いている状態ではlistboxとして(「リストから選択してください」など)

適切に情報を提供することができます。

このように、一見矛盾しているように見える仕様も、実際のユーザーインタラクションとアクセシビリティの要件を満たすための設計的な配慮として理解することができます。

ChatGPT

WAI-ARIA の role="option" の仕様を読むと、一見すると option ロールの親要素は listbox または group (その親が listbox である場合) でなければならないように思えます。しかし、HTML の select タグとその option タグの関係を考えると、矛盾があるように感じられるかもしれません。

1. WAI-ARIA の仕様と HTML の実装の関係

WAI-ARIA の仕様では、option ロールの Required Accessibility Parent Roleslistboxgroup (親が listbox) が指定されています。これは、WAI-ARIA を手動で適用する場合のルールです。つまり、開発者が role="option" を適用する場合、適切な親要素 (listbox など) の下に配置しなければならないという意味になります。

一方、HTML の select 要素は、WAI-ARIA における combobox として認識されることが多いですが、内部的にはユーザーエージェントが適切にアクセシビリティツリーを構築します。その際、option 要素の親として select 要素が直接来ることは問題になりません。

2. select のデフォルトのアクセシビリティツリー

ブラウザの実装によっては、select (特に size 属性なしの単純なドロップダウン) は、内部的に combobox を持つ 独自のアクセシビリティ構造 を持ち、listbox に相当する要素を作成して、その中に option 要素を配置する場合があります。そのため、開発者が明示的に WAI-ARIA を適用しなくても、適切な構造になることが多いです。

一方、size 属性が 2 以上の select (<select size="2"> など) は、デフォルトで listbox のように振る舞い、WAI-ARIA の role="listbox" を明示的に指定しなくても、アクセシビリティツリー上は listbox のように扱われることが一般的です。

3. 矛盾ではなく「ブラウザの適切な対応」

このように、HTML の select 要素は ブラウザが内部的に適切なアクセシビリティ構造を提供する ため、option の親が明示的な listbox でない場合でも、スクリーンリーダーなどは適切に解釈できます。

したがって、開発者が WAI-ARIA を手動で適用する場合 は、仕様に沿って listbox の中に option を配置するべきですが、ネイティブの select を使う場合 は、ブラウザが適切に処理するため、矛盾のように見えても問題はないのです。

4. まとめ

  • option の Required Parent Role に listbox があるのは WAI-ARIA を手動で適用する場合 のルール。
  • ネイティブの select 要素では、ブラウザが内部で適切なアクセシビリティツリーを作成するため、このルールを開発者が意識する必要はない。
  • selectsize 属性が 2 以上の場合、listbox に近い動作をし、option の親として適切な役割を果たす。

つまり、WAI-ARIA の仕様は「HTML の標準要素を置き換えるカスタム実装向けのガイドライン」として考えるのがよく、HTML の select は適切に処理されるため、矛盾を感じる必要はないということです。

Gemini 2.0 Flash

おっしゃる通り、selectタグとoptionタグの関係性と、WAI-ARIAにおけるロールの定義の間には、一見すると矛盾があるように見えます。

WAI-ARIAにおけるselect要素の扱い

WAI-ARIAでは、select要素はデフォルトでcomboboxロールを持つとされています。これは、select要素がユーザーの入力を受け付けるコンポーネントとして扱われるためです。一方、optionタグはデフォルトでoptionロールを持ちますが、optionロールの親ロールとして許可されているのはlistboxまたはgroup with parent listboxのみです。

なぜこのような定義になっているのか?

この背景には、WAI-ARIAがWebアクセシビリティを向上させるために、セマンティクス(意味)とプレゼンテーション(見え方)を分離するという考え方があります。

  • セマンティクス: select要素は、ユーザーに選択肢を提供し、その中から一つを選択させるという意味を持っています。
  • プレゼンテーション: ブラウザは、この意味を理解し、select要素をドロップダウンリストとして表示します。

WAI-ARIAは、このプレゼンテーションをカスタマイズできるように、comboboxロールを提供しています。例えば、JavaScriptなどを使って、select要素をautocomplete機能付きのテキストボックスとして表示したり、複数の選択肢をリスト表示したりすることができます。

矛盾の解消

では、なぜoptionロールの親ロールがlistboxに限定されているのでしょうか?これは、optionロールがリストの中から選択される項目であるという意味を持つためです。select要素をカスタマイズしてlistboxのような表示にした場合、その子要素はoptionロールを持つことが適切となります。

つまり、WAI-ARIAのロールの定義は、select要素の意味と、その表示を柔軟に対応できるように設計されているのです。

まとめ

  • select要素はデフォルトでcomboboxロールを持ちますが、これはプレゼンテーションをカスタマイズするためのものです。
  • optionタグはデフォルトでoptionロールを持ち、その親ロールはlistboxに限定されています。これは、optionロールがリスト項目であることを意味するためです。
  • WAI-ARIAのロールの定義は、セマンティクスとプレゼンテーションを分離し、柔軟なWebアクセシビリティを実現するためのものです。

ご不明な点がございましたら、お気軽にご質問ください。

紐付け

ロールとタグを紐付けてそれを制約とすることで覚える内容を減らす。また、ロールの内容とタグの意味付けを考慮した紐づけを行い覚えやすくする。

  • type属性が"xxx"であるinputタグをinput [xxx]と表記
  • scope属性が"xxx"であるthタグをth [xxx]と表記
  • コンセプト列は公式のロールに書かれている以下項目のタグ
    • Base Concept
    • Related Concepts
  • タグのロール列はそのロールに関連するタグ
    • tag は暗黙ロールが設定されているタグ
    • (tag) は設定可能なロールになっているタグ (暗黙ロールタグが存在しない)
  • 主観設定列はいくつかの理由により紐付けた方がよいと思ったタグ
    • メモ列に理由が書いてある
  • これら3つの要素からタグ列のタグを決定している
    • 基本的にコンセプト列,タグのロール列が尊重されている = 基本公式準拠
  • タグ視点で説明すると以下のようになる
    • 設定可能なロールがない場合 -> ロールのことは考えない
    • 設定可能なロールがAnyの場合 -> 特別用途を指定されていないと見なす
      • 暗黙ロールを尊重して通常指定しないと見なす (特別な事情がない限り指定しない)
    • 暗黙ロールが"No correspoinding role"で、設定可能なロールがある場合 -> 通常指定しないと見なす
      • 恣意的に暗黙ロールに設定していないと見なす (特別な事情がない限り指定しない)
Link of role and tag
ロール タグ コンセプト タグのロール 主観設定 メモ
document html html
article article article article
comment div - div
generic * div, span * * * 特別な事情がない限り暗黙ロールのまま使用する
none * * * * 文脈に応じて使用可能なタグで使用する
rowgroup thead, tbody, tfoot thead, tbody, tfoot thead, tbody, tfoot
separator hr hr hr
meter meter meter meter
progressbar progress progress
columnheader th [col] th [col] th [col]
heading h0 h0 h0
rowheader th [row] th [row] th [row]
tab li (h0, li, a, img, button, input [button]) li <li>以外は<li>の中に定義可能なため
alert output (section) output outputは多くのブラウザで"aria-live"領域として実装されているため
alertdialog dialog (dialog, section) dialog alertと違い対話型が想定されるため
blockquote blockquote blockquote blockquote
caption caption caption, figcaption, legend caption <figcaption>, <legend>はcaptionを選択不能
cell td td td, th
code code code code
definition dd, div, span dd dd, div, span <div>, <span>は<dfn>に対応するため
deletion s, del s, del s, del
emphasis em em em
figure figure figure figure
group hgroup, fieldset, optgroup, details, address, div fieldset hgroup, fieldset, optgroup, details, address hgroup, fieldset, optgroup, details, address, div <div>は汎用的なグルーピングのため
toolbar menu (menu, ol, ul) menu 対話的要素が想定されるため
image img img img
insertion ins ins ins
list ul, ol ul, ol ul, ol, menu
feed article (article, aside, section) article feedの内容は<article>が想定され理解しやすいため
listitem li li li
treeitem li (li, a, img, button, input [button]) li <li>以外は<li>の中に定義可能なため
log div (section) div <section>の用途を限定するため
mark mark mark mark
marquee div (section) div <section>の用途を限定するため
math math math math
note div (aside, section) div <aside>, <section>はlandmarkと認識した方が覚えやすいため
paragraph p p p
status output output output
timer div, span - div, span
strong strong strong strong
subscript sub sub, sup sub
suggestion div, span - div, span
superscript sup sub, sup sup
table table table table
tabpanel section (section) section
term dt, dfn dfn dt, dfn dt, dfn
time time time time
tooltip div - div
banner header header header
complementary aside aside aside
contentinfo footer footer footer
form form form form
main main main main
navigation nav nav nav
region section section section
search search search search
gridcell td td td, th
row tr tr tr
checkbox input [checkbox] input [checkbox] input [checkbox]
switch button, input [checkbox] (a, img, button, input [button], input [checkbox]) button, input [checkbox] Form関連要素が理解しやすいため
combobox select select select
option option option option
radio input [radio] input [radio] input [radio]
slider input [range] input [range]
spinbutton input [number] input [number]
textbox textarea, input [text] textarea, input [text] textarea, input [text]
searchbox input [search] input [search] input [search]
button button button button
link link, a, area link, a link, a, area
menuitem li (li, a, img, button, input [button], input [checkbox], input [radio]) li <li>以外は<li>の中に定義可能なため
grid table table (table)
treegrid table (table) table
tablist menu (nav, menu, ol, ul) menu 基本的にtabは対話的要素であり<nav>はlandmarkと認識した方が覚えやすいため
listbox select, datalist select select, datalist
menu menu (nav, menu, ol, ul, select) menu role名と一致している方が覚えやすいため
menubar menu (nav, menu, ol, ul) menu 対話的要素が想定され<nav>はlandmarkと認識した方が覚えやすいため
radiogroup fieldset (menu, ol, ul, fieldset) fieldset
tree ol (menu, ol, ul) ol 順序が重要なため
dialog dialog dialog

プロパティの厳選

使用しないプロパティ

以下のプロパティは基本的に使用しない。

プロパティ 理由
aria-activedescendant Active=Focusと解釈すればFocus状態から推論可能なため
aria-atomic live regionの詳細設定用のため
aria-autocomplete Form系要素を使用する前提であれば推論可能なため
aria-braillelabel 点字について知らず使えないため
aria-brailleroledescription 点字について知らず使えないため
aria-colcount 文書構造から推論可能なため
aria-colindex 文書構造から推論可能なため
aria-colindextext 用途が限られるため
aria-colspan 文書構造から推論可能なため
aria-disabled Form系要素を使用する前提であれば推論可能であり、構造に対して必要な場合は限られるため
aria-dropeffect Deprecated in ARIA 1.1
aria-flowto 文書構造やtabindexから推論可能なため
aria-grabbed Deprecated in ARIA 1.1
aria-level 適切なHeadingタグや階層構造で推論可能なため
aria-modal dialogタグのメソッド使い分けで自動設定されるため
aria-multiline タグの使い分けで推論可能なため
aria-multiselectable selectタグを使用する前提であれば推論可能であり、その他の用途は限られるため
aria-owns 親子関係を文書構造で表現する前提であれば推論可能なため
aria-placeholder Form系要素を使用する前提であれば推論可能なため
aria-readonly Form系要素を使用する前提であれば推論可能なため
aria-relevant live regionの詳細設定用のため
aria-required Form系要素を使用する前提であれば推論可能なため
aria-roledescription Accessible Name等で代替可能なため
aria-rowcount 文書構造から推論可能なため
aria-rowindex 文書構造から推論可能なため
aria-rowindextext 用途が限られるため
aria-rowspan 文書構造から推論可能なため
aria-sort 動的テーブル系ロール用プロパティのため
aria-valuemax タグの属性から推論可能なため
aria-valuemin タグの属性から推論可能なため
aria-valuenow タグの属性から推論可能なため

なぜaria-disabledを使用しないか

入力項目については、そもそも個人的にdisabled項目を表示するメリットがないと思うため、必要になった時に表示(要素追加)する方が良いように思っている。ミラーの法則やプログレッシブディスクロージャーの原則などもあるが、個人の体感としても表示されている項目は少なければ少ないほど圧迫感が少なく入力意欲が削がれないと感じる。また、フォーカスされないという点もreadonlyを使用せずdisabledにしている時点でフォーカス可能にする必要性を感じない。また、VoiceOverでは関係なく選択して読み上げできたという検証結果もあるため、わざわざaria-disabledを使用すべきだと思わない。
ボタンについても、押下可能になる条件が不明瞭になりがちなため、そもそもdisabledにするメリットがないと思っている。なぜユーザーが押下してはならない対話的要素がページに存在するようにしなければならないのか、と思ってしまうため今のところdisabledやaria-disabledの必要性を感じていない。見栄えだけ調整し、押下した時に条件に応じてアクセシブルな説明と実行停止をすれば良いだけだと思える。他要素との依存性をスクリプトだけに隔離できる事や、条件が実行スクリプト内で明示される点もより良いと感じる。

用途整理

動的更新区域(Live-region)定義用

プロパティ 設定可能値 設定可能ロール メモ
aria-live off, polite, assertive all status,alertロールの設定で代用可能
aria-busy false, true all 更新中のLive-region要素で使用

対話的要素の不正値用

プロパティ 設定可能値 設定可能ロール メモ
aria-invalid false, true, grammar, spelling textbox, searchbox, switch, checkbox, combobox, listbox, radiogroup, slider, spinbutton, columnheader, rowheader, gridcell, tree, treegrid
aria-errormessage id textbox, searchbox, checkbox, combobox, listbox, radiogroup, slider, spinbutton, switch, tree, columnheader, rowheader, gridcell, treegrid Live-region要素のidを設定

Accesible Name設定用

プロパティ 設定可能値 設定可能ロール
aria-label "string" all
aria-labelledby id all

別区域で詳細説明する用

プロパティ 設定可能値 設定可能ロール メモ
aria-description "string" all
aria-describedby id all 構造化されていない文字列での説明
aria-details id all 構造化されている文書区域での説明

Paging等の集合の一部だけを表示する用

全ての要素が文書上に現れている場合は設定不要。

プロパティ 設定可能値 設定可能ロール
aria-posinset "integer" article, listitem, menuitem, tab, radio, option, comment, row, treeitem
aria-setsize "integer" article, listitem, menuitem, tab, radio, option, comment, row, treeitem

視覚や操作等の暗黙情報を明示する用

プロパティ 設定可能値 設定可能ロール メモ
aria-controls id all 他要素を操作する場合に使用
aria-current false, true, page, step, location, date, time all 現在位置を示すため参考のような用途で使用
aria-haspopup false, true, menu, listbox, grid, tree, dialog button, link, menuitem, tab, combobox, textbox, slider, gridcell, treeitem Overlay表示のトリガー要素等で使用
aria-hidden false, true, undefined all 装飾要素等で使用
aria-orientation horizontal, vertical, undefined separator, listbox, tablist, radiogroup, slider, menu, menubar, toolbar, tree, treegrid ロールによって暗黙設定あり
aria-keyshortcuts "string" all ショートカットキーがある場合

特定の用途だけで使用する用

プロパティ 設定可能値 使用ロール メモ
aria-checked false, true, mixed, undefined switch switchロールでのみ使用
aria-pressed false, true, mixed, undefined button トグルボタンの実装でのみ使用
aria-selected false, true, undefined tab tabロールでのみ使用
aria-expanded false, true, undefined tab tabロールでのみ使用
aria-valuetext "string" meter, progressbar aria-valuenowの数値として表現できない場合のみ使用

ロールとの関連

  • 名列はAccessible Nameの設定について
    • oは必須、xは不可、空白は可能を表す
  • 暗黙値列はそのロールを設定すると自動で設定されるプロパティ
  • 設定要列はMUSTとして表現されているプロパティ
  • 設定すべき列はSHOULDとして表現されているプロパティ
  • メモ列は文章で記載されていた気を付ける事項
Role and properties
ロール 暗黙値 設定要 設定すべき メモ
document - - -
banner - - - ページに1つだけ設定すべき
complementary - - -
contentinfo - - - ページに1つだけ設定すべき
form o - - - 検索フォームはsearchロールを使用すべき; 各要素にラベルを付けなければならない; 可視ラベルがある場合、aria-labelledbyを設定すべき; ラベルは見出しに含めるべき; 明示的なsubmit操作以外でsubmitする場合、事前に通知すべき
main - - - ページに1つだけ設定すべき
navigation - - -
region o - - - その他のランドマークが適切でない場合にのみ使用すべき; 可視ラベルがある場合、aria-labelledbyを設定すべき; ラベルは見出しに含めるべき
search - - -
comment - - - コメントと被コメント要素の関連性を特定すべき
generic - - - コンテンツでこのロールを使用すべきでない; noneやgroupを使用してもよい
none - - -
image o - - -
link o - - -
figure - - - 本文からこのロールに参照を提供すべき; captionが説明の場合、aria-detailsを設定すべき
separator aria-orientation="horizontal" - -
heading o - aria-level - Chromeではタグ種類に応じて自動的にaria-levelが付与されている
group - - - 入れ子にしてもよい; 対話的要素の集合構造を構成するためにこのロールを使用すべき
log aria-live="polite" - -
marquee aria-live="off" - -
toolbar aria-orientation="horizontal" - - 複数存在する場合、ラベルを付けなければならない; Focusを管理してもよい
dialog o - - - Focus可能な要素を持つべき; モーダルの場合、子要素にFocusを移動させるべき
alertdialog o - - aria-describedby モーダルにすべき; 子要素にFocusを移動させるべき; aria-describedbyを設定すべき
note - - - 本文にaria-describedby,aria-detailsを設定するとよい
timer aria-live="off" - - 進行中はテキストを更新し続けるべき
tooltip - - - 参照元要素にaria-describedbyを設定すべき
button o - - - トグルボタンにはaria-pressedを設定しなければならない
checkbox o - aria-checked - inputタグを使用する場合、aria-checkedは設定すべきでない
switch o - aria-checked -
combobox o aria-haspopup="listbox" aria-expanded - selectタグを使用しない場合、満たすべき条件あり
radiogroup o - - -
radio o - aria-checked - radiogroupを用いて明示的にグループ化されていることを保証すべき
slider o aria-orientation="horizontal", aria-valuemin="0", aria-valuemax="100" aria-valuenow -
spinbutton o - - -
textbox o - - -
searchbox o - - -
meter o aria-valuemin="0", aria-valuemax="100" aria-valuenow - 進行状況を表現するためにmeterを使用すべきでない
progressbar o aria-valuemin="0", aria-valuemax="100" - - 特定領域読み込み進行状況の場合、aria-describedbyを設定し、特定領域にaria-busy="true"を設定すべき
alert aria-live="assertive", aria-atomic="true" - - Focusをメッセージに移す場合、alertdialogロールを使用すべき
status aria-live="polite", aria-atomic="true" - - このロールを制御する要素にaria-controlsを設定すべき
paragraph x - - - このロールが無いと意味が変わってしまう場合にのみ使用すべき
strong x - - - 装飾のために使用すべきでない
mark x - - - このロールが無いと意味が変わってしまう場合にのみ使用すべき
emphasis x - - -
code x - - - このロールが無いと意味が変わってしまう場合にのみ使用すべき
subscript x - - - このロールが無いと意味が変わってしまう場合にのみ使用すべき
superscript x - - -
time x - - -
blockquote - - -
math - - - 画像の場合は数式のラベル,説明を関連付けるべき
term x - - aria-describedby, aria-details 対話的要素にこのロールを使用すべきでない
definition x - - - 定義されるtermロールを特定しなければならない; 対話的要素にこのロールを使用すべきでない
table o - - - ソートを含む対話的操作が可能な場合、gridかtreegridを使用すべき
grid o - - - 満たすべき条件あり
treegrid o - - - 満たすべき条件あり
caption x - - - このロールが名前を表す場合、親要素はaria-labelledbyを設定すべき
rowgroup - - -
row - - - treegrid以外でaria-expanded,aria-level,aria-posinset,aria-setsizeを設定してはならない
columnheader o - - -
rowheader o - - -
cell - - -
gridcell - - -
menu aria-orientation="vertical" - - このロールの子孫含めFocusを管理すべき
menubar aria-orientation="horizontal" - - このロールの子孫含めFocusを管理すべき; デスクトップのメニューバーに似ていることを保証すべき
menuitem o - - - サブメニューを持つ場合、aria-haspopup="true"を設定し、活性化時にサブメニューを表示すべき; separatorを用いて集合を分離してよい
list - - -
listitem - - -
tree o aria-orientation="vertical" - - このロールの子孫含めFocusを管理すべき
treeitem o - - - 通常aria-selected,aria-checkedの両方を設定すべきでない
tablist aria-orientation="horizontal" - - 選択方式(単一,複数)により満たすべき条件あり; このロールの子孫含めFocusを管理すべき
tab o aria-selected="false" - aria-selected 選択方式(単一,複数)により満たすべき条件あり
tabpanel o - - - aria-labelledbyを設定するか、tabにaria-controlsを設定すべき
suggestion x - - - 子を持たなければならない; 改訂された場合、その明示とこのロールの削除をすべき
insertion x - - -
deletion x - - -
feed - - -
article - - -
listbox o aria-orientation="vertical" - - 子孫のoptionロールのFocusを管理すべき
option o - - - optionタグを使用しない場合、満たすべき条件あり

結論

以上の情報整理や紐付け制約をベースに、情報を追加付与する条件を纏めた。多くの場合ここに記載のないものは意識しなくても大きな問題はないと思われる。

制約

制約を設けた方が認知負荷が下がり大きな問題も起きないと総合的に判断した内容。

  • hrタグ(separatorロール)はフォーカス不可とする
  • a,areaタグはhref属性を設定する
  • imgタグはalt属性を設定し、空文字列以外の値を指定する
  • 親子関係がややこしいtemplate,noscript,scriptは考慮外とする

文書構造としての枠組み

<html>  <!-- role="document" -->
  <head>
    <title>text only</title>
    <meta name="description" content="description text" />
    ...
  </head>
  <body>
    <header>  <!-- role="banner" (Landmark) -->
      <search>  <!-- role="search" (Landmark) -->
        <input type="search" />  <!-- role="searchbox" -->
      </search>
    </header>
    <nav></nav>  <!-- role="navigation" (Landmark) -->
    <main>       <!-- role="main" (Landmark) -->
      ...
    </main>
    <aside></aside>    <!-- role="complementary" (Landmark) -->
    <footer></footer>  <!-- role="contentinfo" (Landmark) -->
  </body>
</html>
  • header,footerをLandmarkとするにはmainsection等の外側に配置する必要がある
    • それらはページに1つだけ設置すべき
  • sectionをLandmarkとするにはAccessible Nameを設定する必要がある (role="region")
    • 実際はsection以外のLandmark系タグで十分と思われるため上記では省いた
  • formもLandmarkとなる (role="form")

親子制約がある条件(セット)

  • コメント内のロールは設定される暗黙ロールを表す
  • タグの子部分のコメントは許容される内容を表す

HTMLによる制約

<details>  <!-- role="group" -->
  <summary><!-- Phrasing,Heading --></summary>
  ... <!-- Flow -->
</details>
<hgroup>  <!-- role="group" -->
  <h0></h0> <!-- parent is not limited to <hgroup>; role="heading" -->
  <p></p>   <!-- parent is not limited to <hgroup>; role="paragraph" -->
</hgroup>
<fieldset>  <!-- role="group" -->
  <legend><!-- Phrasing,Heading --></legend>
  ... <!-- Flow -->
</fieldset>
<textarea>text</textarea>  <!-- role="textbox" -->
<picture>
  <source />
  <img alt="as acc name" /> <!-- parent is not limited to <picture>; role="image" -->
</picture>
<audio>
  <source />
  <track />
  ... <!-- Transparent -->
</audio>
<video>
  <source />
  <track />
  ... <!-- Transparent -->
</video>
<figure>  <!-- role="figure" -->
  <figcaption><!-- Flow --></figcaption>
  ... <!-- Flow -->
</figure>
<dl>
  <!-- <div> can be put here -->
    <dt><!-- Flow --></dt>  <!-- role="term" -->
    <dd><!-- Flow --></dd>  <!-- role="definition" -->
  <!-- </div> -->
</dl>
<ruby>
  ... <!-- Phrasing -->
  <rp>text</rp>
  <rt><!-- Phrasing --></rt>
  <rp>text</rp>
</ruby>
<map> <!-- <map> is an ancestor of <area>  -->
  <area href="./path" />  <!-- role="link" -->
  ... <!-- Transparent -->
</map>

ロールによる制約

<div role="suggestion">
  <ins></ins>  <!-- parent is not litited to suggestion; role="insertion" -->
  <del></del>  <!-- parent is not litited to suggestion; role="deletion" -->
</div>
<article role="feed">
  <article></article>  <!-- parent is not litited to feed; role="article" -->
</article>

HTMLとロールの複合制約

<ul>  <!-- role="list" -->
  <li><!-- Flow --></li>  <!-- role="listitem" -->
</ul>
<ol>  <!-- role="list" -->
  <li><!-- Flow --></li>  <!-- role="listitem" -->
</ol>
<ol role="tree">
  <!-- <div role="group"> can be put here -->
  <li role="treeitem"><!-- Flow --></li>
  <!-- <div role="group"> -->
</ol>
<menu role="menu">
  <li role="menuitem"><!-- Flow --></li>
  <li role="none"><hr /></li>
</menu>
<menu role="menubar">
  <li role="menuitem"><!-- Flow --></li>
  <li role="none"><hr aria-orientation="vertical" /></li>
</menu>
<menu role="toolbar">
  <li role="none"><!-- Flow --></li>
  <li role="none"><hr aria-orientation="vertical" /></li>
</menu>
<menu role="tablist">
  <li id="xxx" role="tab" aria-selected="true" aria-expanded="true"><!-- Flow --></li>
</menu>
<section role="tabpanel" aria-labelledby="xxx"><!-- Flow --></section>
<select>  <!-- role="combobox" -->
  <!-- <optgroup> can be put here -->  <!-- role="group" -->
    <option>text</option>  <!-- role="option" -->
  <!-- </optgroup> -->
  <!-- <hr role="none" /> can be put -->
</select>
<datalist>  <!-- role="listbox" -->
  <option>text</option>  <!-- role="option" -->
  <!-- or Phrasing -->
</datalist>
<!-- simple structure -->
<table>  <!-- role="table" -->
  <tr>  <!-- role="row" -->
    <td><!-- Flow --></td>  <!-- role="cell" -->
  </tr>
</table>

<!-- full structure -->
<table> <!-- if required, add role="grid" or role="treegrid" -->
  <caption><!-- Flow --></caption>  <!-- role="caption" -->
  <colgroup>
    <col span="2" />
  </colgroup>
  <thead>  <!-- role="rowgroup" -->
    <tr>  <!-- role="row" -->
      <th scope="col"><!-- Flow --><th>  <!-- role="columnheader" -->
      <th scope="col"><!-- Flow --><th>  <!-- role="columnheader" -->
    </tr>
  </thead>
  <tbody>  <!-- role="rowgroup" -->
    <tr>  <!-- role="row" -->
      <th scope="row"><!-- Flow --><th>  <!-- role="rowheader" -->
      <td><!-- Flow --></td> <!-- if change role of <table>, add role="gridcell" -->
    </tr>
  </tbody>
  <tfoot>  <!-- role="rowgroup" -->
    <tr>  <!-- role="row" -->
      <th scope="row"><!-- Flow --><th>  <!-- role="rowheader" -->
      <td><!-- Flow --></td> <!-- if change role of <table>, add role="gridcell" -->
    </tr>
  </tfoot>
</table>

注意が必要な条件

  • ややこしくなるため以下タグはLandmark以外で使用しない
    • header,footer,main,nav,aside,search
  • sectionはregion(Landmark)かtabpanelロールとして使用する
    • Landmarkとして使用するには以下のように記述する
      <section aria-labelledby="xxx">  <!-- role="region" (landmark) -->
        <h1 id="xxx"></h1>  <!-- role="heading" as accessible name of <section> -->
        ...
      </section>
      
  • formはformロール(Landmark)になる
    • 目的を説明する簡単なラベルを付ける
    • ラベルを見出しに含めてaria-labelledby属性を設定する
  • dl,dt,ddを用いない単発の単語定義は例えば以下のように記述する
    <dfn aria-describedby="xxx"><!-- Phrasing --></dfn>  <!-- role="term" -->
    <span id="xxx" role="definition"><!-- Phrasing --></span>
    
  • 対話的要素にはラベル(Accessible Name)を付ける
  • tableにはcaption(Accessible Name)を付ける
  • aには必ずhref属性を設定する
  • imgには必ずalt属性を設定し、空文字列以外を指定する
  • dialogで警告やエラーメッセージを表示する場合はalertdialogロールを使用する
    • alertdialogロールとする時はモーダルダイアログとして表示する
    • aria-describedby属性を設定すべき
  • meter,progressタグは必ずmax属性を設定する
    • HTMLではmaxのデフォルト値は1.0だが、WAI-ARIAのロールでは100になる
  • meter,progressタグで現在値が数値で表現できない場合はaria-valuetextを設定する
  • input [radio]をまとめるfieldsetにはradiogroupロールを使用する
  • outputはその内容を変化させる対話的要素にaria-controls属性を設定する
  • outputでエラーメッセージを表示する場合はロールをalertに設定後、テキストを変更する
  • output以外に動的に表示が変化する区域にはdivaria-live属性を設定する
    • 読み込み中はaria-busy属性を設定する
  • タイマー表示をする場合はtimerロールを使用し、aria-live属性を適切に設定する
  • ツールチップを作る場合はtooltipロールを使用し、参照元要素にaria-describedbyを設定する
  • トグルボタンを作る場合はbuttonaria-pressed属性を設定して作成する
  • スイッチを作る場合はbuttoninput [checkbox]でswitchロールを使用する
    • buttonの場合はaria-checked属性を設定する
  • 参考のようなUIを使用する場合はaria-current属性を設定する
  • 対話的要素で不正な値が存在する時は、aria-invalid,aria-errormessage属性を設定する
  • 対話的要素でダイアログ以外のOverlay表示が増える場合はaria-haspopup属性を設定する
  • 対話的要素で親子関係でない要素に影響を与える場合はaria-controls属性を設定する
  • 完全に単なる視覚的な装飾である場合はaria-hidden="true"を設定する
  • ページングなど要素集合の全てが現れていない場合、aria-setsize,aria-posinset属性を設定する
  • 以下のロールを使用したい場合はdivを使用する
    • group,comment,log,note,tooltip,definition,timer,suggestion,marquee
  • 便宜的にdivspanを使用する場合は何もロールを付けずに使用する

雑記

非常に時間がかかりました。裏ではもう少しまとまったいくつかの表としているのですが、記事にすると相当見にくいですね。組織が違うので当たり前なのですが、文書を見ているとHTML Living StandardとWAI-ARIAで完璧に分かれているため両方の整合性を保った理解をするのが非常に面倒でした。罰則も軽いのでISO統合マネジメントシステムのような統合運用規約が無いと色々難しいように思います。5年以内にAGI,ASIが出てくるのでASIがAI記述用の完全に合理的な新Web仕様を策定してくれることを願います。

参考文献

脚注
  1. 令和6年(2024年)4月1日から、障害者差別解消法(障害を理由とする差別の解消の推進に関する法律)の改正により、国や地方公共団体などに義務付けられている合理的配慮の提供が、民間の事業者も義務化されました。 ウェブアクセシビリティとは? 分かりやすくゼロから解説! ↩︎

1

Discussion

ログインするとコメントできます