checkbox
Marca un elemento como casilla de verificación de dos o tres estados. Se recomienda usar <input type="checkbox"> en primer lugar; recurra a role="checkbox" solo cuando no pueda utilizar el elemento nativo — por ejemplo, al construir un control de tres estados que deba mostrar un valor mixto.
Cuándo usar
Use <input type="checkbox">. El elemento nativo proporciona foco, activación con Espacio, la pseudoclase :checked, envío de formularios y la propiedad JS indeterminate para el estado triestado. role="checkbox" existe para dos casos:
- Necesita una casilla de verificación triestado expuesta como
aria-checked="mixed"(un «seleccionar todo» que refleja el estado de los elementos secundarios). - Un sistema de diseño incluye un componente de casilla personalizado que no se puede reemplazar.
Si implementa role="checkbox" en un elemento que no es un <input>, debe establecer aria-checked (es obligatorio), gestionar tabindex="0" y manejar el evento keydown para Espacio.
Contrato de teclado y foco
Según el patrón de casilla de verificación de la APG:
- Tab mueve el foco a la casilla de verificación.
- Espacio alterna
aria-checkedentre"true"y"false"(y"mixed"en el caso triestado). - Enter NO activa una casilla de verificación — solo Espacio. (Los elementos nativos también ignoran Enter en la mayoría de los navegadores.)
El foco permanece en la casilla de verificación después de la activación.
Errores frecuentes
role="checkbox"sin atributoaria-checkedestablecido. El estado es obligatorio desde el momento en que el elemento está en el DOM.- Usar
aria-checked="true"solo como gancho de clase — actualizando el aspecto visual pero sin actualizar nunca el atributo al hacer clic. - Casillas personalizadas que responden al clic pero no a Espacio.
- Anidar un
<input>nativo dentro de un<div role="checkbox">— la semántica duplicada confunde a los lectores de pantalla. - Controles triestado que recorren Espacio en el ciclo false → true → mixed → false. La APG especifica false → true → false; mixed lo establece la página mediante programación, no el usuario.
Ejemplo
<!-- Recomendado -->
<label>
<input type="checkbox" name="terms" required>
Acepto los términos y condiciones
</label>
<!-- «Seleccionar todo» personalizado triestado -->
<div
role="checkbox"
tabindex="0"
aria-checked="mixed"
aria-labelledby="selectAllLabel"
>
</div>
<span id="selectAllLabel">Select all rows</span>