Atajos de teclado

Tab
Navegar entre elementos interactivos
Shift + Tab
Navegación hacia atrás
Entrée / Espace
Activar botones y enlaces
Échap
Cerrar modales y menús
↑ ↓
Navegar en listas y menús

Navegación con teclado en listas

Mal ejemplo

Menú solo con navegación Tab:

<!-- Malo: Solo navegación Tab -->
<div class="menu">
  <div tabindex="0">🏠 Inicio</div>
  <div tabindex="0">📋 Proyectos</div>
  <div tabindex="0">👥 Equipo</div>
  <div tabindex="0">📊 Estadísticas</div>
  <div tabindex="0">⚙️ Configuración</div>
</div>

<!-- El usuario debe presionar Tab 5 veces -->
<!-- Sin navegación de flechas -->
<!-- Sin semántica de menú -->

Buen ejemplo

Menú con navegación de flechas:

💡 Usa ↑ ↓ para navegar, Enter para seleccionar

<!-- Bueno: navegación de flechas con roving tabindex -->
<div
  role="menu"
  @keydown="handleKeydown"
>
  <div
    v-for="(item, i) in items"
    role="menuitem"
    :tabindex="selected === i ? 0 : -1"
    @focus="selected = i"
    :class="{ selected: selected === i }"
  >
    {{ item }}
  </div>
</div>
// Navegación de flechas con roving tabindex
function handleKeydown(e) {
  switch(e.key) {
    case 'ArrowDown':
      selected = (selected + 1) % items.length
      break
    case 'ArrowUp':
      selected = selected === 0
        ? items.length - 1
        : selected - 1
      break
    case 'Enter':
      selectItem(selected)
      break
  }
}

Explicación: Las listas navegables con teclado permiten usar las teclas de flecha para moverse entre elementos, además de la navegación clásica con Tab.

Estilos de enfoque visibles

Mal ejemplo

Intenta navegar con Tab en esta área:

Enlace a página
/* ❌ Elimina todos los indicadores de enfoque */
*:focus {
  outline: none !important;
}

button:focus,
a:focus,
input:focus {
  outline: none !important;
}
<!-- ❌ Problemas de accesibilidad: -->
<button>Botón 1</button>        <!-- Sin tipo, enfoque invisible -->
<button>Botón 2</button>        <!-- Sin tipo, enfoque invisible -->
<a href="#">Enlace</a>           <!-- Enfoque invisible -->
<input type="text" />         <!-- Enfoque invisible -->

<!-- Navegación con teclado imposible de seguir visualmente -->

Buen ejemplo

Intenta navegar con Tab en esta área:

Enlace a página
/* ✅ Indicadores de enfoque visibles y accesibles */
button:focus-visible {
  outline: 3px solid #4F46E5;
  outline-offset: 2px;
}

input:focus-visible {
  border-color: #4F46E5;
  outline: 2px solid #4F46E5;
  outline-offset: 1px;
}
<button type="button">Botón 1</button>
<button type="button">Botón 2</button>
<a href="#">Enlace a página</a>
<input type="text" placeholder="Ingresa texto" />

Explicación: Los usuarios que navegan con teclado necesitan indicadores visuales claros para saber dónde están en la página.

Enlace de salto (Skip to content)

Mal ejemplo

Contenido principal

El usuario debe navegar por todos los enlaces de navegación...

<!-- Malo: sin enlace de salto -->
<header>
  <nav>
    <a href="#">Inicio</a>
    <a href="#">Productos</a>
    <a href="#">Servicios</a>
    <!-- 10+ enlaces de navegación... -->
  </nav>
</header>
<main>
  <!-- El usuario debe atravesar toda la navegación -->
  <h1>Contenido principal</h1>
</main>

Buen ejemplo

Contenido principal

¡El usuario puede acceder directamente aquí gracias al enlace de salto!

/* Enlace de salto oculto por defecto, visible al enfocar */
.skip-link {
  position: absolute;
  top: -100px;
  left: 1rem;
  z-index: 1000;
  padding: 0.5rem 1rem;
  background: var(--color-primary);
  color: white;
  text-decoration: none;
  border-radius: 0.625rem;
}

.skip-link:focus {
  top: 1rem;
}
<a href="#main-content" class="skip-link">
  Saltar al contenido principal
</a>
<header>
  <nav aria-label="Navegación principal">
    <ul>
      <li><a href="/">Inicio</a></li>
      <li><a href="/produits">Productos</a></li>
      <li><a href="/services">Servicios</a></li>
    </ul>
  </nav>
</header>
<main id="main-content">
  <h1>Contenido principal</h1>
</main>

Explicación: Los enlaces de salto permiten a los usuarios de teclado saltar directamente al contenido principal sin tener que pasar por toda la navegación.

Modal con trampa de enfoque

Mal ejemplo

Buen ejemplo

Explicación: Los modales deben mantener el enfoque dentro y permitir cerrar con la tecla Escape. El enfoque debe volver al elemento que abrió el modal.