outline: none sin un estilo de foco de reemplazo
Una sola línea de CSS está dejando silenciosamente a los usuarios de teclado fuera de tu app. outline: none sin reemplazo elimina el anillo de foco del navegador — la única señal visual que tiene un usuario de teclado para saber "estás aquí". En un flujo de login o de checkout, no es un bug cosmético: es una puerta cerrada con llave.
Por qué existe el anillo de foco
Cada elemento interactivo — enlaces, botones, inputs — recibe del navegador un contorno de foco por defecto. Los usuarios de teclado con visión (power users, personas con discapacidades motoras, cualquiera cuyo trackpad murió) recorren la página con Tab y dependen de ese anillo para saber qué elemento recibirá la próxima tecla. Si lo quitas, la página sigue funcionando, pero de forma invisible: el foco se mueve, nada cambia en pantalla y el usuario navega a ciegas.
La documentación de MDN sobre la propiedad outline es directa: si se elimina el estilo de foco por defecto, el elemento debe recibir un reemplazo evidente. WCAG codifica la misma regla en el criterio de éxito 2.4.7 Focus Visible (nivel AA): toda interfaz operable por teclado necesita un modo donde el indicador de foco sea visible.
No es un problema de nicho. El análisis 2026 de WebAIM sobre el millón de páginas de inicio más visitadas encontró fallas WCAG detectables en el 95.9% de ellas — un promedio de 56 errores por página. El foco invisible es uno de los contribuyentes clásicos, y suele entrar al código como un solo "reset" bien intencionado.
Por qué los equipos lo borran
Los diseñadores ven el anillo aparecer cuando el usuario hace clic en un botón y lo consideran feo. Eso pasa porque :focus coincide con cada evento de foco — mouse, touch y teclado por igual. El viejo arreglo era outline: none, que "resolvía" el caso del mouse rompiendo el caso del teclado.
El arreglo moderno: :focus-visible
:focus-visible coincide solo cuando el navegador decide que el usuario realmente necesita ver el foco — en la práctica: sí para navegación con teclado, no para clics de mouse en la mayoría de los controles. Es Baseline con soporte amplio en navegadores desde marzo de 2022. Eso permite tener los dos resultados a la vez:
/* 1. Quiet the ring for pointer clicks */
:focus:not(:focus-visible) {
outline: none;
}
/* 2. Give keyboard users a real indicator */
:focus-visible {
outline: 2px solid currentColor;
outline-offset: 2px;
}
currentColor mantiene el anillo alineado con la marca automáticamente (hereda el color del texto del elemento), outline-offset agrega espacio para que el anillo no quede pegado al borde, y los outlines no cuestan nada en layout — no ocupan espacio y hasta siguen el border-radius en navegadores modernos.
Reglas prácticas
| Situación | Haz esto |
|---|---|
| El anillo aparece al hacer clic con el mouse | Estiliza :focus-visible, no :focus |
outline: none heredado en el código | Haz grep; empareja cada uno con una regla :focus-visible |
| Estilo de foco personalizado | ≥2px, contraste alto contra el fondo, outline-offset: 2px |
| Inputs de texto | Mantén un indicador visible también en :focus — los navegadores lo muestran ahí incluso con puntero, por diseño |
| Navegadores muy viejos | Fallback con @supports not selector(:focus-visible) que estilice :focus |
Trucos de power user
- Audita con un comando.
grep -rn "outline: *none\|outline: *0" src/styles/encuentra a todos los infractores. Cada resultado se borra o recibe su pareja:focus-visible. - Conviértelo en regla de lint. Los plugins de Stylelint orientados a accesibilidad pueden marcar
outline: nonesin estilo de foco acompañante, para que la regresión no vuelva a salir a producción. - Prueba como falla. Suelta el mouse y recorre con Tab tu flujo crítico — inicio de sesión, agregar al carrito, checkout. Si en algún momento pierdes la pista de dónde estás, también la pierde cada usuario de teclado.
- No te quedes solo en el outline. Un estilo de foco visible pero de 1px y bajo contraste sigue fallándole a los usuarios en la práctica; MDN advierte que cambiar estilos de foco sin cuidado puede dañar la usabilidad casi tanto como eliminarlos.
Recursos
:focus-visible— MDNoutline— MDN (advertencia de accesibilidad sobreoutline: none)outline-offset— MDN- Understanding WCAG 2.4.7 Focus Visible — W3C
- The WebAIM Million — análisis anual de accesibilidad
¿Construyendo una funcionalidad con AI? Yeda AI diseña, audita y entrega sistemas LLM de producción.