ARIA: grid ロール
グリッド (grid
) ロールは、1 つ以上のセルの行を含むウィジェット用です。 各セルの位置は重要であり、キーボード入力を使用してフォーカスすることができます。
<table role="grid" aria-labelledby="id-select-your-seat">
<caption id="id-select-your-seat">
座席を選んでください
</caption>
<tbody role="presentation">
<tr role="presentation">
<td></td>
<th>列 A</th>
<th>列 B</th>
</tr>
<tr>
<th scope="row">通路 1</th>
<td tabindex="0">
<button id="1a" tabindex="-1">1A</button>
</td>
<td tabindex="-1">
<button id="1b" tabindex="-1">1B</button>
</td>
<!-- その他の列 -->
</tr>
<tr>
<th scope="row">通路 2</th>
<td tabindex="-1">
<button id="2a" tabindex="-1">2A</button>
</td>
<td tabindex="-1">
<button id="2b" tabindex="-1">2B</button>
</td>
<!-- その他の列 -->
</tr>
</tbody>
</table>
説明
グリッドウィジェットは、テーマに沿ったインタラクティブなコンテンツの 1 つ以上のセルを持つ 1 つ以上の行を含みます。 それは特定の視覚的表現を暗示するものではありませんが、要素間の関連性を暗示します。 用途は、表形式の情報の表示 (データグリッド) と他のウィジェットのグループ化 (レイアウトグリッド) の 2 つのカテゴリーに分類されます。 データグリッドとレイアウトグリッドの両方が同じ ARIA のロール、ステート、およびプロパティを採用している場合でも、そのコンテンツと目的の違いは、キーボードインタラクションのデザインにおいて考慮すべき重要な要因を表面化させます。 詳細については、WAI-ARIA Authoring Practices を参照してください。
セル要素には、行ヘッダーや列ヘッダーでない限り、グリッドセル (gridcell
) ロールがあります。 ヘッダー要素には、それぞれ行ヘッダー (rowheader
) ロールと列ヘッダー (columnheader
) ロールがあります。 セル要素は、行 (row
) ロールを持つ要素によって所有される必要があります。 行は行グループ (rowgroup
) を使用してグループ化できます。
グリッドをインタラクティブなウィジェットとして使用する場合は、キーボードインタラクションを実装する必要があります。
関連する ARIA のロール、ステート、プロパティ
ロール
- treegrid (サブクラス)
-
グリッドに展開や折りたたみができる列がある場合は、ツリーグリッドを使用できます。
- row
-
グリッド内の行。
- rowgroup
-
1 つ以上の行 (row) を含むグループ。
ステートとプロパティ
- aria-level
-
他の構造内でのグリッドの階層レベルを示します。 (訳注: この属性は、グリッドロールでは、ARIA 1.2 で、サポートされなくなる予定です。 行ロールでは、引き続きサポートされています。)
- aria-multiselectable
-
aria-multiselectable
がtrue
に設定されている場合、グリッド内の複数の項目を選択できます。 デフォルト値はfalse
です。 - aria-readonly
-
ユーザーがグリッドをナビゲートできるが、グリッドの値を変更できない場合は、
aria-readonly
をtrue
に設定するべきです。 デフォルト値はfalse
です。
メモ: 多くのユースケースでは、HTML の表 (table
) 要素で十分であり、その要素にはすでに多くの ARIA ロールが含まれています。
キーボードインタラクション
キーボードユーザーはグリッドに出会うと、左、右、上、下のキーを使用して行と列をナビゲートします。 インタラクティブなコンポーネントをアクティブ化するには、リターンキーとスペースキーを使用します。
キー | アクション |
---|---|
→ | 1 セル右にフォーカスを移動します。 フォーカスが行の右端のセルにある場合、フォーカスは移動しません。 |
← | 1 セル左にフォーカスを移動します。 フォーカスが行の左端のセルにある場合、フォーカスは移動しません。 |
↓ | 1 セル下にフォーカスを移動します。 フォーカスが列の最下部のセルにある場合、フォーカスは移動しません。 |
↑ | 1 セル上にフォーカスを移動します。 フォーカスが列の最上部のセルにある場合、フォーカスは移動しません。 |
Page Down | 作成者が決定した行数だけ下にフォーカスを移動します。 通常、現在表示されている行セットの一番下の行が最初に表示される行の 1 つになるようにスクロールします。 フォーカスがグリッドの最後の行にある場合、フォーカスは移動しません。 |
Page Up | 作成者が決定した行数だけ上にフォーカスを移動します。通常、現在表示されている行セットの一番上の行が最後に表示される行の 1 つになるようにスクロールします。 フォーカスがグリッドの最初の行にある場合、フォーカスは移動しません。 |
Home | フォーカスを含む行の最初のセルにフォーカスを移動します。 |
End | フォーカスを含む行の最後のセルにフォーカスを移動します。 |
ctrl + Home | 最初の行の最初のセルにフォーカスを移動します。 |
ctrl + End | 最後の行の最後のセルにフォーカスを移動します。 |
セル、行、列を複数選択できる場合は、次のキーの組み合わせが一般的に使用されます。
キーの組み合わせ | アクション |
---|---|
ctrl + Space | フォーカスを含む列を選択します。 |
shift + Space | フォーカスを含む行を選択します。 グリッドに行を選択するためのチェックボックス付きの列が含まれている場合、このキーの組み合わせを使用して、フォーカスがチェックボックスにない場合でもそのボックスをチェックできます。 |
ctrl + A | すべてのセルを選択します。 |
shift + → | 選択範囲を 1 セル右側に拡張します。 |
shift + ← | 選択範囲を 1 セル左側に拡張します。 |
shift + ↓ | 選択範囲を 1 セル下側に拡張します。 |
shift + ↑ | 選択範囲を 1 セル上側に拡張します。 |
例
カレンダーの例
HTML
<table role="grid" aria-labelledby="calendarheader">
<caption id="calendarheader">
September 2018
</caption>
<thead role="rowgroup">
<tr role="row">
<td></td>
<th role="columnheader" aria-label="Sunday">S</th>
<th role="columnheader" aria-label="Monday">M</th>
<th role="columnheader" aria-label="Tuesday">T</th>
<th role="columnheader" aria-label="Wednesday">W</th>
<th role="columnheader" aria-label="Thursday">T</th>
<th role="columnheader" aria-label="Friday">F</th>
<th role="columnheader" aria-label="Saturday">S</th>
</tr>
</thead>
<tbody role="rowgroup">
<tr role="row">
<th scope="row" role="rowheader">Week 35</th>
<td>26</td>
<td>27</td>
<td>28</td>
<td>29</td>
<td>30</td>
<td>31</td>
<td role="gridcell" tabindex="-1">1</td>
</tr>
<tr role="row">
<th scope="row" role="rowheader">Week 36</th>
<td role="gridcell" tabindex="-1">2</td>
<td role="gridcell" tabindex="-1">3</td>
<td role="gridcell" tabindex="-1">4</td>
<td role="gridcell" tabindex="-1">5</td>
<td role="gridcell" tabindex="-1">6</td>
<td role="gridcell" tabindex="-1">7</td>
<td role="gridcell" tabindex="-1">8</td>
</tr>
<!-- … Additional Rows … -->
</tbody>
</table>
CSS
table {
margin: 0;
border-collapse: collapse;
font-variant-numeric: tabular-nums;
}
tbody th,
tbody td {
padding: 5px;
}
tbody td {
border: 1px solid #000;
text-align: right;
color: #767676;
}
tbody td[role="gridcell"] {
color: #000;
}
tbody td[role="gridcell"]:hover,
tbody td[role="gridcell"]:focus {
background-color: #f6f6f6;
outline: 3px solid blue;
}
JavaScript
var selectables = document.querySelectorAll('table td[role="gridcell"]');
selectables[0].setAttribute("tabindex", 0);
var trs = document.querySelectorAll("table tbody tr"),
row = 0,
col = 0,
maxrow = trs.length - 1,
maxcol = 0;
Array.prototype.forEach.call(trs, function (gridrow, i) {
Array.prototype.forEach.call(
gridrow.querySelectorAll("td"),
function (el, i) {
el.dataset.row = row;
el.dataset.col = col;
col = col + 1;
},
);
if (col > maxcol) {
maxcol = col - 1;
}
col = 0;
row = row + 1;
});
function moveto(newrow, newcol) {
var tgt = document.querySelector(
'[data-row="' + newrow + '"][data-col="' + newcol + '"]',
);
if (tgt && tgt.getAttribute("role") === "gridcell") {
Array.prototype.forEach.call(
document.querySelectorAll("[role=gridcell]"),
function (el, i) {
el.setAttribute("tabindex", "-1");
},
);
tgt.setAttribute("tabindex", "0");
tgt.focus();
return true;
} else {
return false;
}
}
document.querySelector("table").addEventListener("keydown", function (event) {
switch (event.key) {
case "ArrowRight":
moveto(
parseInt(event.target.dataset.row, 10),
parseInt(event.target.dataset.col, 10) + 1,
);
break;
case "ArrowLeft":
moveto(
parseInt(event.target.dataset.row, 10),
parseInt(event.target.dataset.col, 10) - 1,
);
break;
case "ArrowDown":
moveto(
parseInt(event.target.dataset.row, 10) + 1,
parseInt(event.target.dataset.col, 10),
);
break;
case "ArrowUp":
moveto(
parseInt(event.target.dataset.row, 10) - 1,
parseInt(event.target.dataset.col, 10),
);
break;
case "Home":
if (event.ctrlKey) {
var i = 0;
var result;
do {
var j = 0;
var result;
do {
result = moveto(i, j);
j++;
} while (result == false);
i++;
} while (result == false);
} else {
moveto(parseInt(event.target.dataset.row, 10), 0);
}
break;
case "End":
if (event.ctrlKey) {
var i = maxrow;
var result;
do {
var j = maxcol;
do {
result = moveto(i, j);
j--;
} while (result == false);
i--;
} while (result == false);
} else {
moveto(
parseInt(event.target.dataset.row, 10),
document.querySelector(
'[data-row="' + event.target.dataset.row + '"]:last-of-type',
).dataset.col,
);
}
break;
case "PageUp":
var i = 0;
var result;
do {
result = moveto(i, event.target.dataset.col);
i++;
} while (result == false);
break;
case "PageDown":
var i = maxrow;
var result;
do {
result = moveto(i, event.target.dataset.col);
i--;
} while (result == false);
break;
case "Enter":
alert(event.target.textContent);
break;
}
event.preventDefault();
});
より多くの例
- データグリッドの例 (英語)
- レイアウトグリッドの例 (英語)
- W3C/WAI チュートリアル: 表 (英語)
アクセシビリティに関する懸念
キーボードインタラクションが適切に実装されていても、矢印キーを使用しなければならないことに気づかないユーザーもいます。 グリッド (grid
) ロールを使用して、必要な機能性とインタラクションが最もよく達成できることを確認してください。
仕様書
Specification |
---|
Accessible Rich Internet Applications (WAI-ARIA) # grid |
スクリーンリーダーのサポート
TBD
関連情報
- ARIA composite ロール
- ARIA table ロール
- ARIA treegrid ロール
- ARIA row ロール
- ARIA rowgroup ロール
- ARIA: gridcell ロール
- ARIA: rowheader ロール
- ARIA: columnheader ロール
- HTML の表要素
- aria-level
- aria-multiselectable
- aria-readonly
- WAI-ARIA ロール
alertdialog ロールの使用
ARIA: alert ロール
ARIA: application ロール
ARIA: article ロール
ARIA: banner ロール
ARIA: button ロール
ARIA: cell ロール
ARIA: checkbox ロール
ARIA: complementary ロール
ARIA: contentinfo ロール
ARIA: dialog ロール
ARIA: document ロール
ARIA: feed ロール
ARIA: figure ロール
ARIA: form ロール
ARIA: generic ロール
ARIA: grid ロール
ARIA: gridcell ロール
ARIA: heading ロール
ARIA: img ロール
ARIA: list ロール
ARIA: listbox ロール
ARIA: listitem ロール
ARIA: main ロール
ARIA: navigation ロール
ARIA: none ロール
ARIA: option ロール
ARIA: radio ロール
ARIA: region ロール
ARIA: row ロール
ARIA: rowgroup ロール
ARIA: search ロール
ARIA: spinbutton ロール
ARIA: switch ロール
ARIA: tab ロール
ARIA: table ロール
ARIA: term ロール
ARIA: textbox ロール
ARIA: tooltip ロール
group ロールの使用
link ロールの使用
log ロールの使用
presentation ロールの使用
progressbar ロールの使用
slider ロールの使用
status ロールの使用
toolbar ロールの使用