Standardy · ARIA

Rola Widget

checkbox

Oznacza element jako pole wyboru o dwóch lub trzech stanach. Najpierw użyj <input type="checkbox">; sięgaj po role="checkbox" tylko wtedy, gdy nie możesz użyć natywnego elementu — na przykład przy budowaniu kontrolki tri-state, która musi pokazywać wartość mieszaną.

Kiedy używać

Używaj <input type="checkbox">. Natywny element zapewnia fokus, aktywację spacją, pseudoklasę :checked, wysyłanie formularza i właściwość JS indeterminate dla tri-state. role="checkbox" istnieje dla dwóch przypadków:

  • Potrzebujesz pola wyboru tri-state eksponowanego jako aria-checked="mixed" (np. „zaznacz wszystkie” odzwierciedlające stan potomków).
  • System projektowania dostarcza niestandardowy komponent pola wyboru, którego nie możesz zastąpić.

Jeśli implementujesz role="checkbox" na elemencie niebędącym inputem, musisz ustawić aria-checked (jest wymagane), zarządzać tabindex="0" i obsługiwać keydown dla spacji.

Kontrakt klawiaturowy i fokus

Zgodnie z wzorcem APG dla checkbox:

  • Tab przenosi fokus na pole wyboru.
  • Space przełącza aria-checked między "true" a "false" (oraz "mixed" dla tri-state).
  • Enter NIE aktywuje pola wyboru — tylko Space. (Natywne inputy też ignorują Enter w większości przeglądarek.)

Fokus pozostaje na polu wyboru po aktywacji.

Typowe błędy

  • role="checkbox" bez ustawionego atrybutu aria-checked. Stan jest wymagany od momentu, gdy element pojawi się w DOM.
  • Używanie aria-checked="true" tylko jako haka klasowego — aktualizowanie wyglądu wizualnego bez aktualizowania atrybutu po kliknięciu.
  • Niestandardowe pola wyboru reagujące na kliknięcie, ale nie na Space.
  • Owijanie natywnego <input> wewnątrz <div role="checkbox"> — zduplikowana semantyka myli czytniki ekranu.
  • Kontrolki tri-state, w których Space cyklicznie przechodzi przez false → true → mixed → false. APG określa false → true → false; mixed jest ustawiane programowo przez stronę, nie przez użytkownika.

Przykład

<!-- Preferowane -->
<label>
  <input type="checkbox" name="terms" required>
  Akceptuję regulamin
</label>

<!-- Niestandardowe „zaznacz wszystkie" tri-state -->
<div
  role="checkbox"
  tabindex="0"
  aria-checked="mixed"
  aria-labelledby="selectAllLabel"
>
</div>
<span id="selectAllLabel">Zaznacz wszystkie wiersze</span>