Actualizado 15 de julio de 2026

Indicadores de foco que se ven de verdad

Una forma habitual de que esto salga mal: a mitad de un rediseño, alguien nota que el contorno de foco por defecto del navegador choca con los botones nuevos y añade outline: none a la hoja de estilos de reset. El control de calidad visual pasa, porque nada se ve distinto, hasta que llega el primer informe de alguien que navega con teclado y va tabulando por una página que ya no muestra dónde está.

Un indicador de foco es la marca visible del elemento sobre el que actuará la entrada de teclado, y quitarlo vuelve una interfaz inutilizable sin ratón. WCAG 2.4.7 exige un indicador de foco visible en el nivel AA, y el indicador necesita un contraste de 3:1 con los colores que lo rodean. La solución que funciona: nunca uses outline: none sin un reemplazo, aplica estilo al anillo con :focus-visible y asegúrate de que se vea sobre cualquier fondo en el que pueda aterrizar. Esa última parte es donde la mayoría de los anillos fallan en silencio, y es la parte que este apartado de nuestra guía de contraste trabaja con números calculados.

¿Por qué existen los indicadores de foco?

Quien usa ratón tiene una respuesta permanente a “¿dónde estoy?”: el puntero está en pantalla y el elemento que hay debajo responde. Quien recorre una página con teclado usando Tab tiene exactamente un equivalente: el indicador de foco. Lo mismo vale para quienes usan dispositivos de conmutación (switch) y para cualquiera cuyas manos, vista o configuración hagan poco práctico el ratón. El anillo no es decoración encima de la navegación; es la retroalimentación de la navegación.

Ese es el marco intuitivo de outline: none: no ordena un detalle visual, apaga el puntero de alguien. La interfaz sigue funcionando en el sentido de que Tab sigue moviendo el foco, pero de forma invisible, lo que para quien tabula equivale a que no funcione.

¿Qué exigen las reglas de WCAG?

El requisito central es el Criterio de Éxito 2.4.7, Foco Visible: cualquier interfaz operable con teclado debe mostrar un indicador de foco visible. Se sitúa en el nivel AA —el nivel que la regulación suele referenciar—, así que un anillo ausente es un incumplimiento normativo, no una decisión de estilo.

La visibilidad tiene un número asociado. El criterio de contraste de no-texto pide 3:1 de la información visual necesaria para identificar los componentes de la interfaz, y un indicador de foco es exactamente ese tipo de información, así que el piso operativo es 3:1 entre el anillo y los colores contiguos.

WCAG 2.2 amplió el panorama: Foco No Oculto (2.4.11, AA) dice que el elemento enfocado no puede quedar totalmente escondido detrás de otro contenido —las cabeceras fijas y los banners de cookies son los culpables habituales— y un criterio AAA más estricto describe con más detalle el tamaño mínimo y el contraste del indicador. Los detalles del nivel AAA son opcionales y se persiguen con menos frecuencia; las conclusiones fiables son el anillo visible, el piso de 3:1 y no enterrar el elemento enfocado.

¿Qué reemplaza a outline: none?

La razón histórica por la que quienes diseñan borraban el anillo es que :focus también se dispara con los clics de ratón, así que los botones seguían iluminándose tras hacer clic. Ese problema tiene una solución con forma de selector: :focus-visible coincide cuando el navegador juzga que el foco debe mostrarse —navegación con teclado, en esencia— y omite los clics de ratón normales.

/* deja que los clics de ratón sean silenciosos, conserva el anillo para el teclado */
:focus {
  outline: none;
}
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
}

Esto conserva la estética que motivó el borrado y el salvavidas que el borrado cortó. Una advertencia: empareja las dos reglas como arriba; outline: none en :focus solo, sin una regla :focus-visible al lado, recrea el fallo original.

¿Por qué un solo color de anillo rara vez funciona en todas partes?

Porque el anillo se comprueba contra lo que sea en lo que aterrice, y un producto real tiene muchos fondos. Aquí hay un solo color de anillo —un azul de marca, #2563eb— probado contra cuatro superficies con las que se encontraría de verdad, con cada ratio calculado:

SuperficieAnillo vs superficiePiso de 3:1
tarjeta blanca #FFFFFF≈5,2:1pasa
panel teñido #EFF6FF≈4,8:1pasa
botón de marca #2563eb1:1invisible
cabecera oscura #111827≈3,4:1pasa, margen estrecho

El fallo no es aleatorio: cae en el botón con el color de marca, que suele ser el elemento más enfocado de la página, y es total: un anillo del mismo color que su fondo no falla gradualmente, desaparece. La cabecera oscura pasa con poco margen. Un color, cuatro veredictos.

Por eso conviene tratar un color de foco como una decisión por superficie más que como una constante global. Abre el panel de roles de foco en Scale Composer: deriva un rol de foco para cada superficie de la paleta y lo comprueba contra esa superficie en el momento de derivarlo, así el anillo que aterriza en el relleno de marca no es el anillo que aterriza en la tarjeta blanca.

Scale Composer mostrando un rol de foco derivado por superficie, cada uno comprobado contra su propio color de fondo con el ratio de contraste mostrado

¿Cómo lo arregla un anillo de dos colores?

Si el diseño quiere un único estilo de foco en todas partes, el patrón robusto es un anillo con dos capas: una línea interior clara y una exterior oscura (o al revés). El razonamiento es aritmético: ningún color por sí solo contrasta con todos los fondos, pero un color claro y uno oscuro entre ambos cubren todo el rango, porque cualquier superficie es o bien lo bastante clara para la capa oscura o bien lo bastante oscura para la clara. Las mismas cuatro superficies, con un anillo interior blanco y un anillo exterior casi negro #111827:

Superficieinterior blancoexterior #111827¿una capa ≥3:1?
tarjeta blanca #FFFFFF1:1≈17,7:1
panel teñido #EFF6FF≈1,1:1≈16,3:1
botón de marca #2563eb≈5,2:1≈3,4:1sí — ambas
cabecera oscura #111827≈17,7:11:1

Cada capa falla en algún sitio; el par no falla en ninguno. En CSS las dos capas suelen ser un outline más un box-shadow, o dos sombras apiladas.

¿Importan el desplazamiento y el grosor?

Sí, y en la misma dirección que el contraste. Una línea fina de 1px pegada al borde del elemento tiende a desaparecer aunque su color pase técnicamente: se lee como parte del borde, y a lo largo de un borde con color es un píxel de información al que se le pide cargar con toda la señal. Un piso operativo común es un anillo de 2px con unos 2px de desplazamiento: el hueco separa el anillo del elemento para que se lea como indicador y no como borde, y el grosor sobrevive al renderizado subpíxel y a las pantallas de menor calidad. El criterio de apariencia AAA de WCAG 2.2 apunta en la misma dirección, pidiendo un indicador de tamaño sustancial, no solo un color que pase.

Dale a cada superficie su propio anillo

La tabla de cuatro superficies de arriba es pequeña; una paleta real tiene más superficies y un cambio de tema las duplica. Deriva roles de foco en tus propias superficies: añade una cabecera oscura o un panel teñido y observa cómo el color de foco se adapta por superficie, con cada emparejamiento comprobado contra el piso de 3:1 a medida que se deriva.

Seguir leyendo