Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

ARIA: grid-Rolle

Die grid-Rolle ist für ein Widget vorgesehen, das eine oder mehrere Zeilen mit Zellen enthält. Die Position jeder Zelle ist von Bedeutung, und jede Zelle kann über die Tastatur fokussiert werden.

Beschreibung

Die grid-Rolle bezeichnet ein zusammengesetztes Widget mit einer oder mehreren Zeilen, die jeweils eine oder mehrere Zellen enthalten. Einige oder alle Zellen im Grid können durch zweidimensionale Navigation, etwa mit den Pfeiltasten, fokussiert werden.

html
<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 Grid-Widget enthält eine oder mehrere Zeilen mit Zellen, deren interaktive Inhalte thematisch zusammengehören. Es schreibt keine bestimmte visuelle Darstellung vor, setzt aber eine Beziehung zwischen den Elementen voraus. Die Anwendungsfälle lassen sich in zwei Kategorien einteilen: die Darstellung tabellarischer Informationen (Daten-Grids) und die Gruppierung anderer Widgets (Layout-Grids). Obwohl beide dieselben ARIA-Rollen, -Zustände und -Eigenschaften verwenden, ergeben sich aus ihren unterschiedlichen Inhalten und Zwecken wichtige Anforderungen an die Gestaltung der Tastaturinteraktion. Weitere Informationen finden Sie im Leitfaden zu ARIA Authoring Practices.

Zellelemente haben die Rolle gridcell, es sei denn, sie sind Zeilen- oder Spaltenüberschriften. In diesem Fall haben sie die Rolle rowheader beziehungsweise columnheader. Zellelemente müssen Elementen mit der Rolle row zugeordnet sein. Zeilen können mithilfe der Rolle rowgroup gruppiert werden.

Ein Grid ist ein interaktives Widget. Daher müssen Tastaturinteraktionen implementiert werden.

Ein zugänglicher Name wird für die Rolle grid dringend empfohlen, auch wenn ARIA ihn nicht vorschreibt. Verwenden Sie aria-labelledby, um auf eine sichtbare Beschriftung zu verweisen, oder aria-label, wenn keine sichtbare Beschriftung vorhanden ist.

Zugehörige ARIA-Rollen, -Zustände und -Eigenschaften

Rollen

treegrid (Unterklasse)

Wenn ein Grid Zeilen enthält, die zum Ein- oder Ausblenden untergeordneter Zeilen auf- oder zugeklappt werden können, kann ein treegrid verwendet werden.

row

Eine Zeile innerhalb des Grids.

rowgroup

Eine Gruppe, die eine oder mehrere row-Zeilen enthält.

Zustände und Eigenschaften

aria-level

Gibt die Hierarchieebene des Grids innerhalb anderer Strukturen an.

aria-multiselectable

Wenn aria-multiselectable auf true gesetzt ist, können mehrere Elemente im Grid ausgewählt werden. Der Standardwert ist false.

aria-readonly

Wenn das Grid die Bearbeitung von Zellinhalten unterstützt, die Bearbeitung aber für alle Zellen nicht verfügbar ist, kann aria-readonly auf true gesetzt werden. Der Standardwert ist false. Das Fehlen des Attributs bedeutet jedoch nicht, dass das Grid bearbeitbare Inhalte enthält. Lassen Sie das Attribut weg, wenn das Grid keine Bearbeitung von Zellinhalten unterstützt. Der für das Grid festgelegte Wert wird an seine gridcells weitergegeben und kann für einzelne gridcells überschrieben werden.

Hinweis: Für viele Anwendungsfälle genügt ein HTML-Element <table>, da es und die verschiedenen Tabellenelemente bereits viele ARIA-Rollen mitbringen.

Tastaturinteraktionen

Wenn Tastaturnutzende zu einem Grid gelangen, navigieren sie mit den Tasten links, rechts, oben und unten durch Zeilen und Spalten. Um eine interaktive Komponente zu aktivieren, verwenden sie die Eingabetaste oder die Leertaste.

Taste Aktion
→ Verschiebt den Fokus um eine Zelle nach rechts. Optional kann der Fokus bei Layout-Grids von der Zelle ganz rechts in einer Zeile zur ersten Zelle der nächsten Zeile wechseln. Befindet sich der Fokus auf der letzten Zelle des Grids, bleibt er dort.
← Verschiebt den Fokus um eine Zelle nach links. Optional kann der Fokus bei Layout-Grids von der Zelle ganz links in einer Zeile zur letzten Zelle der vorherigen Zeile wechseln. Befindet sich der Fokus auf der ersten Zelle des Grids, bleibt er dort.
↓ Verschiebt den Fokus um eine Zelle nach unten. Optional kann der Fokus bei Layout-Grids von der untersten Zelle einer Spalte zur obersten Zelle der nächsten Spalte wechseln. Befindet sich der Fokus auf der letzten Zelle des Grids, bleibt er dort.
↑ Verschiebt den Fokus um eine Zelle nach oben. Optional kann der Fokus bei Layout-Grids von der obersten Zelle einer Spalte zur untersten Zelle der vorherigen Spalte wechseln. Befindet sich der Fokus auf der ersten Zelle des Grids, bleibt er dort.
Page Down Verschiebt den Fokus um eine von den Entwickelnden festgelegte Anzahl von Zeilen nach unten. Üblicherweise wird dabei so gescrollt, dass die unterste der derzeit sichtbaren Zeilen zu einer der ersten sichtbaren Zeilen wird. Befindet sich der Fokus in der letzten Zeile des Grids, bleibt er dort.
Page Up Verschiebt den Fokus um eine von den Entwickelnden festgelegte Anzahl von Zeilen nach oben. Üblicherweise wird dabei so gescrollt, dass die oberste der derzeit sichtbaren Zeilen zu einer der letzten sichtbaren Zeilen wird. Befindet sich der Fokus in der ersten Zeile des Grids, bleibt er dort.
Home Verschiebt den Fokus zur ersten Zelle der aktuell fokussierten Zeile.
End Verschiebt den Fokus zur letzten Zelle der aktuell fokussierten Zeile.
ctrl + Home Verschiebt den Fokus zur ersten Zelle der ersten Zeile.
ctrl + End Verschiebt den Fokus zur letzten Zelle 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 Grid eine Spalte mit Kontrollkästchen zur Auswahl von Zeilen enthält, kann diese Tastenkombination das entsprechende Kästchen aktivieren, auch wenn es nicht fokussiert ist.
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

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

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

js
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

Hinweise zur Barrierefreiheit

Selbst wenn die Tastaturbedienung korrekt implementiert ist, wissen manche Nutzende möglicherweise nicht, dass sie die Pfeiltasten verwenden müssen. Stellen Sie sicher, dass sich die benötigte Funktionalität und Interaktion am besten mit der grid-Rolle umsetzen lässt.

Spezifikationen

Spezifikation
Accessible Rich Internet Applications (WAI-ARIA)
# grid

Siehe auch