Enfoque

Los elementos interactivos, incluidos los controles de formulario, los vínculos y los botones, son enfocables y se pueden seleccionar con la tecla Tab de forma predeterminada. Los elementos enfocables con la tecla Tab forman parte del orden de navegación secuencial por enfoque del documento. Otros elementos son inertes, lo que significa que no son interactivos. Con los atributos HTML, es posible hacer que los elementos interactivos sean inertes y que los elementos inertes sean interactivos.

De forma predeterminada, el orden del enfoque de navegación es el mismo que el orden visual, que es el orden del código fuente. Existen atributos HTML que pueden alterar este orden y propiedades CSS que pueden alterar el orden visual del contenido. Cambiar el orden de tabulación con HTML o el orden de renderización visual con CSS puede perjudicar la experiencia del usuario.

No alteres el orden de tabulación percibido y real con CSS y HTML. Como demuestran los siguientes dos ejemplos, los órdenes de tabulación que difieren del orden esperado visualmente confunden a los usuarios y son perjudiciales para la experiencia del usuario.

En este ejemplo, el valor del atributo tabindex hizo que el orden de las pestañas sea caótico:

En este ejemplo, CSS creó una divergencia entre el orden de tabulación y el orden visual del contenido:

La declaración flex-flow: row-reverse; invirtió el orden visual. Además, se aplicó la propiedad order de CSS a la sexta palabra, "This", lo que la movió visualmente. La secuencia de tabulación es el orden del código, que ya no coincide con el orden visual, lo que genera una desconexión para los usuarios del teclado.

Cómo hacer que los elementos inertes sean interactivos

Los atributos contenteditable y tabindex, al ser atributos globales, se pueden agregar a cualquier elemento, lo que los hace enfocables en el proceso. Los elementos enfocables también se pueden enfocar con un mouse o un puntero, ya sea con el atributo autofocus establecido o con una secuencia de comandos, como con element.focus().

El atributo tabindex

El atributo global tabindex, que se introdujo en atributos, permite que los elementos que, de otro modo, no podrían recibir el enfoque lo obtengan, por lo general, con la tecla Tab, de ahí el nombre.

El atributo tabindex toma un número entero como su valor. Un valor negativo hace que un elemento sea enfocable, pero no navegable con la tecla Tab. Un valor tabindex de 0 hace que el elemento sea enfocable y navegable con la tecla Tab, y agrega el elemento en el que se aplica al orden de navegación secuencial con el enfoque en el orden del código fuente. Un valor de 1 o mayor hace que el elemento sea enfocable y se pueda acceder a él con la tecla Tab, pero lo agrega a una secuencia de tabulación priorizada, por lo que se debe evitar.

En esta página, el botón para compartir, <share-action>, es un elemento personalizado. El tabindex="0" agrega este elemento que normalmente no se puede enfocar al orden de tabulación predeterminado del teclado:

<share-action authors="@front-end.social/@estellevw" data-action="click" data-category="web.dev" data-icon="share" data-label="share, mastodon" role="button" tabindex="0">
  <svg aria-label="share" role="img" xmlns="http://www.w3.org/2000/svg">
    <use href="#shareIcon" />
  </svg>
  <span>Share</span>
</share-action>

Hay otro elemento personalizado en esta página: la navegación local tiene un elemento personalizado con un valor tabindex negativo:

<web-navigation-drawer type="standard" tabindex="-1">

Un atributo tabindex con un valor negativo hace que el elemento sea enfocable, pero no navegable con la tecla Tab. El elemento puede recibir el enfoque, por ejemplo, con HTMLElement.focus(), pero no forma parte del orden de navegación secuencial por enfoque. La convención para los elementos enfocables que no se pueden seleccionar con la tecla Tab es usar tabindex="-1". Si agregas tabindex="-1" a un elemento interactivo, ya no se podrá acceder a él con la tecla Tab.

El método element.focus() se puede usar para establecer el enfoque en elementos enfocables. Los navegadores desplazan los elementos enfocados para que se vean. Por este motivo, evita el uso de element.focus({preventScroll:true}), ya que enfocarse en un elemento no visible es una mala experiencia del usuario.

Si quieres consultar el documento para saber qué elemento tiene el enfoque, usa la propiedad de solo lectura Document.activeElement.

Los elementos con un tabindex de 1 o superior se incluyen en una secuencia de tabulación separada. Como observarás en Codepen, el enfoque con la tecla Tab comienza en una secuencia separada, en orden de menor a mayor valor, antes de pasar por los de la secuencia normal (sin tabindex establecido o tabindex="0") en orden de origen:

tabindex con un valor positivo coloca el elemento en una secuencia de enfoque priorizada, lo que puede generar un caos en el orden del enfoque. Evita modificar el orden del DOM con tabindex. Los órdenes de tabulación alterados no solo pueden crear malas experiencias del usuario, sino que también son difíciles de administrar y mantener para los desarrolladores.

El atributo contenteditable

El atributo contenteditable se analizó anteriormente. Establecer contenteditable="true" en cualquier elemento lo hace editable, enfocable y parte del orden de tabulación. El comportamiento del enfoque es similar al de configurar tabindex="0", pero no es el mismo. Los elementos contenteditable anidados son enfocables, pero no se puede acceder a ellos con la tecla Tab. Para que un elemento contenteditable anidado se pueda navegar con la tecla Tab, agrega tabindex="0", que lo agrega al orden de navegación secuencial con el enfoque.

Cómo asignar autofocus a elementos interactivos

Si bien el atributo booleano autofocus es un atributo global que se puede establecer en cualquier elemento, no hace que un elemento inerte sea interactivo. Cuando se carga la página, el primer elemento enfocable con los atributos autofocus recibe el enfoque, siempre y cuando ese elemento se muestre y no esté anidado en un <dialog>.

Establecer el enfoque automáticamente en el contenido puede ser confuso. Establecer autofocus en un control de formulario significa que el control de formulario se desplazará para mostrarse cuando se cargue la página. Es posible que todos tus usuarios, incluidos los usuarios de lectores de pantalla y los usuarios con ventanas gráficas pequeñas, no "vean" las instrucciones del formulario, e incluso es posible que se desplacen más allá de la etiqueta normalmente visible del control del formulario. El atributo autofocus no altera el orden secuencial de navegación con el enfoque del documento. Se omiten los elementos de la secuencia que preceden al elemento enfocado automáticamente. Por estos motivos, no se recomienda incluir el atributo autofocus.

La excepción a la recomendación de "no usar autofocus" es incluir el atributo autofocus dentro de los elementos <dialog>. Cuando se abre un diálogo, el navegador se enfoca automáticamente en el primer elemento interactivo enfocable dentro de <dialog>, lo que significa que no es necesario agregar autofocus a un elemento. Si quieres asegurarte de que un elemento interactivo específico dentro del diálogo reciba el enfoque cuando se abra el diálogo, agrega el atributo autofocus a ese elemento.

<dialog open>
  <form method="dialog">
    <button type="submit" autofocus>close</button>
  </form>
</dialog>

El atributo autofocus establecido en el cierre <button> permite que reciba el enfoque cuando se abre el diálogo. Como primer elemento del diálogo, habría recibido el enfoque en cualquier caso. De forma predeterminada, cuando se abre un diálogo, el primer elemento enfocable dentro del diálogo recibe el enfoque, a menos que un elemento diferente dentro del diálogo tenga establecido el atributo autofocus.

Haz que los elementos interactivos sean inertes

También hay atributos HTML que pueden quitar elementos interactivos de la secuencia de tabulación. Incluir un tabindex negativo en los elementos enfocables, agregar el atributo disabled a los controles de formulario compatibles y agregar el atributo global inert a un contenedor hacen que los elementos no se puedan navegar con la tecla Tab. Estos tres atributos NO son intercambiables.

Valor de tabindex negativo

Un atributo tabindex con un valor negativo hace que un elemento sea enfocable, pero no navegable con la tecla Tab. Si bien no es necesario agregar tabindex="0" a un elemento que se puede enfocar de forma predeterminada, incluidos los vínculos, los botones, los controles de formulario y los elementos que son contenteditable, incluir un tabindex con un valor negativo quita los elementos que normalmente se pueden enfocar con la tecla Tab del orden de navegación secuencial por enfoque.

Un valor tabindex negativo impide que los usuarios del teclado se enfoquen en los elementos interactivos, pero no inhabilita el elemento. Los usuarios de puntero aún pueden enfocarse en el elemento. Para inhabilitar un elemento, usa el atributo disabled.

Inhabilitado

El atributo booleano disabled hace que los controles de formulario en los que se aplica y sus descendientes, si los hay, no se puedan enfocar. Los controles de formularios inhabilitados no se pueden enfocar, no reciben eventos de clic y no se envían cuando se envía el formulario.

disabled no es un atributo global. Se aplica a <button>, <input>, <optgroup>, <option>, <select>, <textarea>, elementos personalizados asociados a formularios y <fieldset>. Cuando se establece en <optgroup> o <fieldset>, todos los controles de formulario secundarios se inhabilitan, excepto el contenido del primer <legend> de <fieldset>.

Los mismos elementos que admiten disabled también se pueden segmentar con las seudoclases :disabled y :enabled. Los elementos inhabilitados con el atributo disabled suelen tener un estilo de color gris claro con la hoja de estilo del agente de usuario, incluso si se establece un accent-color.

Como es un atributo booleano, la presencia del atributo inhabilita el elemento que, de otro modo, estaría habilitado. No puedes establecerlo en false. Para volver a habilitar un elemento inhabilitado, se debe quitar el atributo, generalmente con Element.removeAttribute('disabled').

La propiedad HTMLInputElement.disabled te permite verificar si una entrada está inhabilitada. Como disabled no es un atributo global, no se hereda de HTMLElement, pero cada interfaz de elemento compatible, como HTMLSelectElement, HTMLTextareaElement, tiene la misma propiedad de solo lectura.

El atributo disabled no se aplica a los elementos inert normales que se hacen enfocables con tabindex o contenteditable, ni tampoco se aplica al elemento <form>. Para inhabilitar estos elementos, se puede usar el atributo global inert.

El atributo inert

Cuando se agrega el atributo booleano global inert a un elemento, ese elemento y todo el contenido anidado se inhabilitan, lo que significa que no se puede hacer clic en ellos ni desplazarse con la tecla Tab hasta ellos. También se quitan del árbol de accesibilidad. Si bien inert se puede aplicar a cualquier elemento, generalmente se usa para secciones de contenido, como contenido fuera de la pantalla o contenido oculto de otro modo.

Cuando se aplica disabled a los controles de formulario, el navegador proporciona un diseño predeterminado y se puede diseñar con la seudoclase :disabled. El atributo inert no proporciona indicadores visuales y no tiene una seudoclase coincidente (aunque sí coincide el selector de atributos [inert]).

Usar inert en contenido visible sin estilos que indiquen la inercia puede generar una mala experiencia del usuario. Como el contenido inerte no está disponible para los usuarios de lectores de pantalla, puede generar confusión cuando los usuarios de lectores de pantalla que pueden ver el contenido en la pantalla ven contenido que no está disponible para las herramientas de accesibilidad. Haz que la inercia sea muy evidente con CSS.

Asegúrate de que el enfoque nunca se mueva a contenido no visible. Todo lo que se renderice fuera de la pantalla y no aparezca automáticamente en la vista cuando se enfoque debe ser inerte. Si el contenido está oculto, pero se muestra cuando se enfoca, como un vínculo para ir al contenido, no es necesario que se vuelva inerte.

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre el enfoque.

Si no se puede enfocar un elemento, ¿cómo se describe?

Vacío.
Vuelve a intentarlo.
Inerte.
Correcto.
Se ocultó.
Vuelve a intentarlo.

¿Qué será verdadero si el elemento tiene un atributo disabled?

No se podrá enfocar.
Correcto.
No se mostrará.
Vuelve a intentarlo.
Si es un elemento de formulario, no se enviará.
Correcto.