Normativas · ARIA

Rol Control

radio

Marca un elemento como una opción única dentro de un grupo mutuamente excluyente. Un radio debe estar dentro de un radiogroup (o un fieldset nativo). Se recomienda usar <input type="radio"> en primer lugar; solo se debe recurrir a role="radio" cuando el elemento nativo sea imposible de usar.

Cuándo utilizarlo

Se debe usar <input type="radio"> agrupados mediante un atributo name compartido, envueltos en <fieldset> con una <legend>. El elemento nativo gestiona de forma gratuita la navegación con teclas de flecha, el índice de tabulación itinerante, la selección exclusiva y el envío del formulario.

role="radio" está reservado para componentes personalizados —controles segmentados, widgets de valoración, selectores con temas— donde no es posible usar el elemento nativo. Un elemento role="radio" DEBE tener un elemento padre (o un destino aria-owns) con role="radiogroup".

Contrato de teclado y foco

Según el patrón de grupo de radio del APG:

  • Tab mueve el foco al interior del grupo, sobre el radio marcado (o el primero si ninguno está marcado).
  • Tab mueve el foco FUERA del grupo. Tab NO recorre los radios entre sí.
  • Las teclas de flecha (Arriba/Abajo o Izquierda/Derecha) mueven el foco al radio siguiente o anterior Y lo marcan. Esto es inusual: la mayoría de los widgets separan el foco de la selección, pero los radios los vinculan.
  • Espacio marca el radio enfocado si aún no está marcado.

Se debe usar un índice de tabulación itinerante: solo el radio actualmente seleccionado tiene tabindex="0"; el resto tiene tabindex="-1".

Errores frecuentes

  • Radios personalizados donde Tab recorre cada opción (en lugar de las teclas de flecha). Rompe el modelo de interacción estándar de los radios.
  • role="radio" sin un role="radiogroup" envolvente. Los lectores de pantalla no pueden anunciar la etiqueta del grupo ni la posición dentro del conjunto.
  • Todos los radios con tabindex="0": cada radio entra en el orden de tabulación, multiplicando las pulsaciones de tecla.
  • aria-checked ausente en el renderizado inicial.
  • Radios personalizados que se desmarcan al volver a presionarlos. Un radio es exclusivo: una vez marcado, la única forma de desmarcarlo es marcar otro del grupo.

Ejemplo

<!-- Recomendado -->
<fieldset>
  <legend>Notification frequency</legend>
  <label><input type="radio" name="freq" value="daily" checked> Daily</label>
  <label><input type="radio" name="freq" value="weekly"> Weekly</label>
  <label><input type="radio" name="freq" value="never"> Never</label>
</fieldset>

<!-- Grupo de radio personalizado -->
<div role="radiogroup" aria-labelledby="freqLabel">
  <span id="freqLabel">Notification frequency</span>
  <div role="radio" aria-checked="true"  tabindex="0">Daily</div>
  <div role="radio" aria-checked="false" tabindex="-1">Weekly</div>
  <div role="radio" aria-checked="false" tabindex="-1">Never</div>
</div>