tab
Marca un elemento como una pestaña dentro de una interfaz con pestañas. Una pestaña DEBE residir dentro de un tablist y DEBERÍA referenciar su tabpanel asociado mediante aria-controls. No existe ningún elemento HTML nativo equivalente — las pestañas son un patrón exclusivo de ARIA.
Cuándo utilizarlo
Para representar una pestaña dentro de una barra de pestañas dispuesta horizontal o verticalmente. Una pestaña DEBE ser un hijo directo de un elemento role="tablist" (o estar incluida mediante aria-owns). Cada pestaña DEBE apuntar a su panel asociado mediante aria-controls="<tabpanel-id>". El reciproco aria-labelledby vive en el panel y apunta de vuelta a la pestaña.
Las pestañas son un patrón de aplicación. Si las «pestañas» enlazan realmente a páginas distintas, conviene utilizar <nav> con enlaces <a> — el cambio de URL hace que el patrón de pestañas resulte incorrecto.
La propia pestaña suele implementarse con un <button>. La semántica del botón se combina de forma limpia con role="tab", y la gestión de foco y activación se obtiene de forma automática.
Contrato de teclado y foco
Según el patrón de pestañas APG:
- Tab desplaza el foco al interior del tablist, situándolo sobre la pestaña activa. Un nuevo Tab mueve el foco FUERA, normalmente hacia el propio tabpanel si dispone de
tabindex="0". - Las teclas de dirección Izquierda/Derecha (o Arriba/Abajo en tablists verticales) mueven el foco entre pestañas.
- Inicio / Fin saltan a la primera / última pestaña.
- La activación puede ser automática (el foco equivale a la selección) o manual (Espacio/Intro para seleccionar). Se recomienda el modo manual cuando activar una pestaña implica operaciones costosas.
Se debe usar un tabindex itinerante («roving tabindex»): solo la pestaña seleccionada tiene tabindex="0".
Errores habituales
- Todas las pestañas con
tabindex="0"— Tab recorre cada pestaña en lugar del panel. - Falta el enlace
aria-controlsque une la pestaña con el tabpanel. aria-selected="true"en más de una pestaña simultáneamente.- Pestañas implementadas con
<a href="#section">— el fragmento de URL cambia, el botón atrás navega entre pestañas y el patrón se rompe. - Sin gestión de foco al activar: al hacer clic en una pestaña se actualiza el panel, pero el siguiente Tab retrocede hasta el encabezado de la página en lugar de entrar en el panel.
Ejemplo
<div role="tablist" aria-label="Account settings">
<button role="tab" id="t-profile" aria-selected="true" aria-controls="p-profile" tabindex="0">Profile</button>
<button role="tab" id="t-billing" aria-selected="false" aria-controls="p-billing" tabindex="-1">Billing</button>
<button role="tab" id="t-security" aria-selected="false" aria-controls="p-security" tabindex="-1">Security</button>
</div>
<section role="tabpanel" id="p-profile" aria-labelledby="t-profile" tabindex="0">…</section>
<section role="tabpanel" id="p-billing" aria-labelledby="t-billing" hidden>…</section>
<section role="tabpanel" id="p-security" aria-labelledby="t-security" hidden>…</section>