ARIA: grid Rolle
Die grid-Rolle ist für ein Widget gedacht, das eine oder mehrere Zeilen von Zellen enthält. Die Position jeder Zelle ist signifikant und kann über Tastatureingaben fokussiert werden.
Beschreibung
Die grid-Rolle ist ein zusammengesetztes Widget, das eine Sammlung von einer oder mehreren Zeilen mit einer oder mehreren Zellen enthält, wobei einige oder alle Zellen im Raster durch Methoden der zweidimensionalen Navigation, wie Richtungspfeiltasten, fokussierbar sind.
<table role="grid" aria-labelledby="id-select-your-seat">
  <caption id="id-select-your-seat">
    Select your seat
  </caption>
  <tbody role="presentation">
    <tr role="presentation">
      <td></td>
      <th>Row A</th>
      <th>Row B</th>
    </tr>
    <tr>
      <th scope="row">Aisle 1</th>
      <td tabindex="0">
        <button id="btn-1a" tabindex="-1">1A</button>
      </td>
      <td tabindex="-1">
        <button id="btn-1b" tabindex="-1">1B</button>
      </td>
      <!-- More Columns -->
    </tr>
    <tr>
      <th scope="row">Aisle 2</th>
      <td tabindex="-1">
        <button id="btn-2a" tabindex="-1">2A</button>
      </td>
      <td tabindex="-1">
        <button id="btn-2b" tabindex="-1">2B</button>
      </td>
      <!-- More Columns -->
    </tr>
  </tbody>
</table>
Ein Raster-Widget enthält eine oder mehrere Zeilen mit einer oder mehreren Zellen von thematisch zusammenhängendem interaktivem Inhalt. Während es keine spezifische visuelle Darstellung impliziert, impliziert es eine Beziehung zwischen den Elementen. Nutzungsmöglichkeiten fallen in zwei Kategorien: Präsentation tabellarischer Informationen (Daten-Raster) und Gruppierung anderer Widgets (Layout-Raster). Obwohl sowohl Daten- als auch Layout-Raster dieselben ARIA-Rollen, -Zustände und -Eigenschaften verwenden, kommen bei Unterschieden in Inhalt und Zweck Faktoren zum Vorschein, die im Design von Tastatur-Interaktionen wichtig sind. Weitere Details finden Sie im ARIA Authoring Practices Leitfaden.
Zellelemente haben die Rolle gridcell, es sei denn, sie sind eine Zeilen- oder Spaltenüberschrift, in diesem Fall sind die Elemente rowheader bzw. columnheader. Zellelemente müssen von Elementen mit einer row Rolle geordnet werden. Zeilen können mit der rowgroup Rolle gruppiert werden.
Wenn das Raster als interaktives Widget verwendet wird, müssen Tastatur-Interaktionen implementiert werden.
Zugehörige ARIA-Rollen, -Zustände und -Eigenschaften
Rollen
- treegrid (Unterklasse)
 - 
Wenn ein Raster Spalten hat, die erweitert oder eingeklappt werden können, kann ein Baumraster verwendet werden.
 - row
 - 
Eine Zeile innerhalb des Rasters.
 - rowgroup
 - 
Eine Gruppe, die eine oder mehrere rows enthält.
 
Zustände und Eigenschaften
- aria-level
 - 
Gibt die hierarchische Ebene des Rasters innerhalb anderer Strukturen an.
 - aria-multiselectable
 - 
Wenn
aria-multiselectableauftruegesetzt ist, können mehrere Elemente im Raster ausgewählt werden. Der Standardwert istfalse. - aria-readonly
 - 
Wenn der Benutzer durch das Raster navigieren kann, aber nicht den Wert oder die Werte des Rasters ändern kann, sollte
aria-readonlyauftruegesetzt sein. Der Standardwert istfalse. 
Hinweis:
Für viele Anwendungsfälle ist ein HTML <table> Element ausreichend, da es und die verschiedenen Tabellenelemente bereits viele ARIA-Rollen enthalten.
Tastatur-Interaktionen
Wenn ein Tastaturbenutzer auf ein Raster stößt, navigiert er durch die Zeilen und Spalten mit den Tasten left, right, top und down. Um die interaktive Komponente zu aktivieren, verwenden sie die Tasten return und space.
| Taste | Aktion | 
|---|---|
| → | Bewegt den Fokus eine Zelle nach rechts. Optional (Layout-Raster), wenn der Fokus auf der rechten Zelle in der Zeile ist, kann der Fokus zur ersten Zelle in der nächsten Zeile verschoben werden. Wenn der Fokus auf der letzten Zelle im Raster ist, bewegt sich der Fokus nicht. | 
| ← | Bewegt den Fokus eine Zelle nach links. Optional (Layout-Raster), wenn der Fokus auf der linken Zelle in der Zeile ist, kann der Fokus zur letzten Zelle in der vorherigen Zeile verschoben werden. Wenn der Fokus auf der ersten Zelle im Raster ist, bewegt sich der Fokus nicht. | 
| ↓ | Bewegt den Fokus eine Zelle nach unten. Optional (Layout-Raster), wenn der Fokus auf der unteren Zelle in der Spalte ist, kann der Fokus zur obersten Zelle in der nächsten Spalte verschoben werden. Wenn der Fokus auf der letzten Zelle im Raster ist, bewegt sich der Fokus nicht. | 
| ↑ | Bewegt den Fokus eine Zelle nach oben. Optional (Layout-Raster), wenn der Fokus auf der obersten Zelle in der Spalte ist, kann der Fokus zur unteren Zelle in der vorherigen Spalte verschoben werden. Wenn der Fokus auf der ersten Zelle im Raster ist, bewegt sich der Fokus nicht. | 
| Page Down | Bewegt den Fokus nach unten um eine vom Autor bestimmte Anzahl von Zeilen, typischerweise so, dass die unterste Zeile im aktuell sichtbaren Satz von Zeilen zu einer der ersten sichtbaren Zeilen wird. Wenn der Fokus in der letzten Zeile des Rasters ist, bewegt sich der Fokus nicht. | 
| Page Up | Bewegt den Fokus nach oben um eine vom Autor bestimmte Anzahl von Zeilen, typischerweise so, dass die oberste Zeile im aktuell sichtbaren Satz von Zeilen zu einer der letzten sichtbaren Zeilen wird. Wenn der Fokus in der ersten Zeile des Rasters ist, bewegt sich der Fokus nicht. | 
| Home | Bewegt den Fokus zur ersten Zelle in der Zeile, die den Fokus enthält. | 
| End | Bewegt den Fokus zur letzten Zelle in der Zeile, die den Fokus enthält. | 
| ctrl + Home | Bewegt den Fokus zur ersten Zelle in der ersten Zeile. | 
| ctrl + End | Bewegt den Fokus zur letzten Zelle in der letzten Zeile. | 
Wenn Zellen, Zeilen oder Spalten ausgewählt werden können, werden häufig die folgenden Tastenkombinationen verwendet:
| Tastenkombination | Aktion | 
|---|---|
| ctrl + Space | Wählt die Spalte aus, die den Fokus enthält. | 
| shift + Space | Wählt die Zeile aus, die den Fokus enthält. Wenn das Raster eine Spalte mit Kontrollkästchen zur Auswahl von Zeilen enthält, kann diese Tastenkombination verwendet werden, um das Kästchen zu markieren, auch wenn der Fokus nicht auf dem Kontrollkästchen liegt. | 
| ctrl + A | Wählt alle Zellen aus. | 
| shift + → | Erweitert die Auswahl um eine Zelle nach rechts. | 
| shift + ← | Erweitert die Auswahl um eine Zelle nach links. | 
| shift + ↓ | Erweitert die Auswahl um eine Zelle nach unten. | 
| shift + ↑ | Erweitert die Auswahl um eine Zelle nach oben. | 
Beispiele
>Kalenderbeispiel
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 1</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 2</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>
    <tr role="row">
      <th scope="row" role="rowheader">Week 3</th>
      <td role="gridcell" tabindex="-1">9</td>
      <td role="gridcell" tabindex="-1">10</td>
      <td role="gridcell" tabindex="-1">11</td>
      <td role="gridcell" tabindex="-1">12</td>
      <td role="gridcell" tabindex="-1">13</td>
      <td role="gridcell" tabindex="-1">14</td>
      <td role="gridcell" tabindex="-1">15</td>
    </tr>
    <tr role="row">
      <th scope="row" role="rowheader">Week 4</th>
      <td role="gridcell" tabindex="-1">16</td>
      <td role="gridcell" tabindex="-1">17</td>
      <td role="gridcell" tabindex="-1">18</td>
      <td role="gridcell" tabindex="-1">19</td>
      <td role="gridcell" tabindex="-1">20</td>
      <td role="gridcell" tabindex="-1">21</td>
      <td role="gridcell" tabindex="-1">22</td>
    </tr>
    <tr role="row">
      <th scope="row" role="rowheader">Week 5</th>
      <td role="gridcell" tabindex="-1">23</td>
      <td role="gridcell" tabindex="-1">24</td>
      <td role="gridcell" tabindex="-1">25</td>
      <td role="gridcell" tabindex="-1">26</td>
      <td role="gridcell" tabindex="-1">27</td>
      <td role="gridcell" tabindex="-1">28</td>
      <td role="gridcell" tabindex="-1">29</td>
    </tr>
    <tr role="row">
      <th scope="row" role="rowheader">Week 6</th>
      <td role="gridcell" tabindex="-1">30</td>
      <td>1</td>
      <td>2</td>
      <td>3</td>
      <td>4</td>
      <td>5</td>
      <td>6</td>
    </tr>
  </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 black;
  text-align: right;
  color: #767676;
}
tbody td[role="gridcell"] {
  color: black;
}
tbody td[role="gridcell"]:hover,
tbody td[role="gridcell"]:focus {
  background-color: #f6f6f6;
  outline: 3px solid blue;
}
JavaScript
const selectables = document.querySelectorAll('table td[role="gridcell"]');
selectables[0].setAttribute("tabindex", 0);
const trs = document.querySelectorAll("table tbody tr");
let rowIndex = 0;
let colIndex = 0;
let maxRow = trs.length - 1;
let maxCol = 0;
trs.forEach((row) => {
  row.querySelectorAll("td").forEach((el) => {
    el.dataset.row = rowIndex;
    el.dataset.col = colIndex;
    colIndex++;
  });
  if (colIndex > maxCol) {
    maxCol = colIndex - 1;
  }
  colIndex = 0;
  rowIndex++;
});
function moveTo(newRow, newCol) {
  const tgt = document.querySelector(
    `[data-row="${newRow}"][data-col="${newCol}"]`,
  );
  if (tgt?.getAttribute("role") !== "gridcell") {
    return false;
  }
  document.querySelectorAll("[role=gridcell]").forEach((el) => {
    el.setAttribute("tabindex", "-1");
  });
  tgt.setAttribute("tabindex", "0");
  tgt.focus();
  return true;
}
document.querySelector("table").addEventListener("keydown", (event) => {
  const col = parseInt(event.target.dataset.col, 10);
  const row = parseInt(event.target.dataset.row, 10);
  switch (event.key) {
    case "ArrowRight": {
      const newRow = col === 6 ? row + 1 : row;
      const newCol = col === 6 ? 0 : col + 1;
      moveTo(newRow, newCol);
      break;
    }
    case "ArrowLeft": {
      const newRow = col === 0 ? row - 1 : row;
      const newCol = col === 0 ? 6 : col - 1;
      moveTo(newRow, newCol);
      break;
    }
    case "ArrowDown":
      moveTo(row + 1, col);
      break;
    case "ArrowUp":
      moveTo(row - 1, col);
      break;
    case "Home": {
      if (event.ctrlKey) {
        let i = 0;
        let result;
        do {
          let j = 0;
          do {
            result = moveTo(i, j);
            j++;
          } while (!result);
          i++;
        } while (!result);
      } else {
        moveTo(row, 0);
      }
      break;
    }
    case "End": {
      if (event.ctrlKey) {
        let i = maxRow;
        let result;
        do {
          let j = maxCol;
          do {
            result = moveTo(i, j);
            j--;
          } while (!result);
          i--;
        } while (!result);
      } else {
        moveTo(
          row,
          document.querySelector(
            `[data-row="${event.target.dataset.row}"]:last-of-type`,
          ).dataset.col,
        );
      }
      break;
    }
    case "PageUp": {
      let i = 0;
      let result;
      do {
        result = moveTo(i, col);
        i++;
      } while (!result);
      break;
    }
    case "PageDown": {
      let i = maxRow;
      let result;
      do {
        result = moveTo(i, col);
        i--;
      } while (!result);
      break;
    }
    case "Enter": {
      console.log(event.target.textContent);
      break;
    }
  }
  event.preventDefault();
});
Weitere Beispiele
Barrierefreiheit
Auch wenn die Tastaturnutzung korrekt implementiert ist, könnten einige Benutzer nicht wissen, dass sie die Pfeiltasten verwenden müssen. Stellen Sie sicher, dass die Funktionalität und Interaktion, die benötigt werden, am besten durch die Verwendung der grid-Rolle erreicht werden können.
Spezifikationen
| Specification | 
|---|
| Accessible Rich Internet Applications (WAI-ARIA)> # grid>  |