Enfoque de estilo

El indicador de enfoque (a menudo representado por un "anillo de enfoque") identifica el elemento enfocado actualmente en tu página. Para los usuarios que no pueden usar un mouse, este indicador es extremadamente importante porque actúa como reemplazo del puntero del mouse.

Si el indicador de enfoque predeterminado del navegador choca con tu diseño, puedes usar CSS para cambiarle el estilo. Recuerda tener en cuenta a los usuarios de teclados.

Usa :focus para mostrar siempre un indicador de enfoque

La seudoclase :focus se aplica cada vez que se enfoca un elemento, sin importar el dispositivo de entrada (mouse, teclado, pluma stylus, etc.) o el método que se use para enfocarlo. Por ejemplo, la <div> que se muestra a continuación tiene un tabindex que la hace enfocable. También tiene un diseño personalizado para su estado :focus:

div[tabindex="0"]:focus {
  outline: 4px dashed orange;
}

Independientemente de si usas un mouse para hacer clic o un teclado para acceder con Tab, el <div> siempre se verá igual.

Desafortunadamente, los navegadores pueden ser inconsistentes con la forma en que aplican el foco. El enfoque de un elemento puede depender del navegador y el sistema operativo.

Por ejemplo, la <button> que se muestra a continuación también tiene un diseño personalizado para su estado :focus.

button:focus {
  outline: 4px dashed orange;
}

Si haces clic en <button> con el mouse en Chrome en macOS, deberías ver su estilo de enfoque personalizado. Sin embargo, no verás el estilo de foco personalizado si haces clic en <button> en Safari para macOS. Esto se debe a que, en Safari, el elemento no recibe el foco cuando haces clic en él.

Debido a que el comportamiento del enfoque es incoherente, es posible que se requieran algunas pruebas en diferentes dispositivos para garantizar que los estilos de enfoque sean aceptables para los usuarios.

Usa :focus-visible para mostrar de manera selectiva un indicador de enfoque

La nueva seudoclase :focus-visible se aplica cada vez que un elemento recibe el foco y el navegador determina, mediante una heurística, que mostrar un indicador de enfoque sería beneficioso para el usuario. En particular, si la interacción más reciente del usuario se realizó mediante el teclado y la tecla que presionaste no incluyó una tecla meta, ALT, OPTION o CONTROL, entonces :focus-visible coincidirá.

El botón del siguiente ejemplo mostrará un indicador de enfoque de manera selectiva. Si usas un mouse para hacer clic en él, los resultados son diferentes a los que usas primero con un teclado para acceder con la tecla Tab.

button:focus-visible {
  outline: 4px dashed orange;
}

Usa :focus-within para aplicar diseño al elemento superior de un elemento enfocado

La seudoclase :focus-within se aplica a un elemento cuando este recibe el enfoque o cuando otro elemento dentro de ese elemento lo recibe.

Se puede usar para destacar una región de la página y llamar la atención del usuario sobre esa área. Por ejemplo, el siguiente formulario recibe el foco cuando se selecciona el formulario en sí y también cuando se selecciona cualquiera de sus botones de selección.

form:focus-within {
  background: #ffecb3;
}

Cuándo mostrar un indicador de enfoque

Una buena regla general es preguntarte: "Si haces clic en este control mientras usas un dispositivo móvil, ¿esperas que muestre un teclado?".

Si la respuesta es "sí", es probable que el control siempre muestre un indicador de enfoque, independientemente del dispositivo de entrada que se use para enfocarlo. Un buen ejemplo es el elemento <input type="text">. El usuario deberá enviar entradas al elemento con el teclado, independientemente de cómo el elemento de entrada recibió el enfoque originalmente, por lo que siempre es útil mostrar un indicador de enfoque.

Si la respuesta es "no", el control puede elegir mostrar de manera selectiva un indicador de enfoque. Un buen ejemplo es el elemento <button>. Si un usuario hace clic en él con un mouse o una pantalla táctil, se completa la acción, y es posible que no se necesite un indicador de enfoque. Sin embargo, si el usuario está navegando con un teclado, sería útil mostrar un indicador de enfoque para que pueda decidir si desea hacer clic en el control con las teclas ENTER o SPACE.

Evita outline: none

La forma en que los navegadores deciden cuándo dibujar un indicador de enfoque es, francamente, muy confusa. Si cambias la apariencia de un elemento <button> con CSS o le asignas una tabindex a un elemento, se iniciará el comportamiento predeterminado del anillo de enfoque del navegador.

Un antipatrón muy común consiste en quitar el indicador de enfoque con CSS, por ejemplo:

/* Don't do this!!! */
:focus {
  outline: none;
}

Una mejor manera de solucionar este problema es usar una combinación de :focus y el polyfill :focus-visible. En el primer bloque de código que aparece a continuación, se muestra cómo funciona el polyfill, y la app de ejemplo que se incluye debajo proporciona un ejemplo de cómo usar el polyfill para cambiar el indicador de enfoque de un botón.

/*
  This will hide the focus indicator if the element receives focus via the
  mouse, but it will still show up on keyboard focus.
*/
.js-focus-visible :focus:not(.focus-visible) {
  outline: none;
}

/*
  Optionally: Define a strong focus indicator for keyboard focus.
  If you choose to skip this step, then the browser's default focus
  indicator will be displayed instead.
*/
.js-focus-visible .focus-visible {
  …
}