Cuadro de diálogo

El elemento de diálogo es útil para representar cualquier tipo de diálogo en HTML. Descubre cómo funciona.

Un diálogo modal es un tipo especial de cuadro emergente en una página web: una ventana emergente que interrumpe al usuario para enfocarse en sí misma. Existen algunos casos de uso válidos para mostrar un diálogo, pero se debe tener mucho cuidado antes de hacerlo. Los diálogos modales obligan a los usuarios a enfocarse en contenido específico y, al menos de forma temporal, a ignorar el resto de la página.

Los diálogos pueden ser modales (solo se puede interactuar con el contenido del diálogo) o no modales (aún es posible interactuar con el contenido fuera del diálogo). Los diálogos modales se muestran sobre el resto del contenido de la página. El resto de la página es inerte y, de forma predeterminada, está oculto por un fondo semitransparente.

El elemento <dialog> HTML semántico para crear un diálogo incluye semántica, interacciones con el teclado y todas las propiedades y métodos de la interfaz HTMLDialogElement.

Este es un ejemplo de un <dialog> modal. Abre el diálogo con el botón “Abrir diálogo modal”. Una vez abierto, hay tres maneras de cerrar el diálogo: la tecla Escape, enviar un formulario con un botón que tenga configurado formmethod="dialog" (o si el formulario tiene configurado method="dialog") y el método HTMLDialogElement.close().

HTMLDialogElement tiene tres métodos principales, junto con todos los métodos heredados de HTMLElement.

dialog.show() /* opens the dialog */
dialog.showModal() /* opens the dialog as a modal */
dialog.close() /* closes the dialog */

Como este <dialog> se abrió a través del método HTMLDialogElement.showModal(), es un diálogo modal. Cuando se abre un diálogo modal, se desactiva y oculta todo excepto el diálogo en sí. Si colocas el cursor sobre la IU fuera del diálogo, notarás que todos los elementos se comportan como si se hubiera configurado pointer-events: none;. Incluso el botón que abre el diálogo no reacciona a las interacciones.

Cuando se abre el diálogo, el enfoque se mueve al diálogo. El enfoque se establece en el primer elemento del orden de navegación secuencial del teclado dentro de ese diálogo. Si presionas la tecla tab de forma repetida, notarás que solo el contenido dentro del diálogo puede enfocarse mientras el diálogo modal está abierto. Todo lo que está fuera del diálogo modal es inerte mientras el diálogo esté abierto.

Cuando se cierra un diálogo, ya sea modal o no, el enfoque se vuelve al elemento que lo abrió. Si abres un diálogo de forma programática que no se basa en la acción del usuario, reconsidera tu decisión. Si es necesario, asegúrate de que el enfoque se restablezca donde estaba antes de que se abriera el diálogo, especialmente si el usuario descarta el diálogo sin interactuar con él.

Hay un atributo inert global que se puede usar para inhabilitar un elemento y todos sus elementos secundarios, excepto cualquier diálogo activo. Cuando se abre un diálogo modal con showModal(), la inercia o la desactivación se incluyen de forma gratuita; el atributo no se establece de forma explícita.

El fondo que oculta todo excepto el diálogo se puede diseñar con el pseudoelemento ::backdrop. El fondo solo se muestra cuando se muestra un <dialog> con el método .showModal(). Este pseudoelemento coincide con todos los fondos, incluido el que se muestra cuando se usa la API de FullScreen, como cuando se ve un video en modo de pantalla completa que no tiene la misma relación de aspecto que la pantalla o el monitor.

Diálogos no modales

De manera similar, HTMLDialogElement.show() abre un diálogo, pero sin agregar un fondo ni hacer que nada se vuelva inerte. La tecla Escape no cierra los diálogos no modales. Por este motivo, es aún más importante que te asegures de incluir un método para cerrar el diálogo no modal. Al hacerlo, si el elemento de cierre está fuera del diálogo, ten en cuenta que el enfoque se dirigirá al elemento que abrió el diálogo, lo que podría no ser la mejor experiencia del usuario.

Si bien la especificación no requiere oficialmente un botón para cerrar el diálogo, considéralo como obligatorio. La tecla Escape cerrará un diálogo modal, pero no uno no modal. Un botón visible que puede recibir enfoque mejora la accesibilidad y la experiencia del usuario.

Cómo cerrar un diálogo

No necesitas el método HTMLDialogElement.close() para cerrar un diálogo. No necesitas JavaScript en absoluto. Para cerrar el <dialog> sin JavaScript, incluye un formulario con un método de diálogo configurando method="dialog" en <form> o formmethod="dialog" en el botón.

Cuando un usuario envía datos a través del método dialog, se mantiene el estado de los datos ingresados por el usuario. Si bien hay un evento de envío (el formulario pasa por la validación de restricciones, a menos que se establezca novalidate), los datos del usuario no se borran ni se envían. Un botón de cierre sin JavaScript se puede escribir de la siguiente manera:

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

Es posible que hayas notado el atributo autofocus configurado en el <button> de cierre en este ejemplo. Los elementos con el atributo autofocus configurado dentro de un <dialog> no recibirán enfoque cuando se cargue la página (a menos que la página se cargue con el diálogo visible). Sin embargo, se enfocarán cuando se abra el diálogo.

De forma predeterminada, cuando se abre un diálogo, el primer elemento enfocable dentro del diálogo recibirá el enfoque, a menos que un elemento diferente dentro del diálogo tenga configurado el atributo autofocus. Configurar el atributo autofocus en el botón de cierre garantiza que reciba el enfoque cuando se abra el diálogo. Sin embargo, incluir autofocus dentro de un <dialog> solo debe hacerse con mucha consideración. Se omiten todos los elementos de la secuencia que aparecen antes del elemento enfocado automáticamente. Analizaremos este atributo con más detalle en la lección de enfoque.

La interfaz HTMLDialogElement incluye una propiedad returnValue. El envío de un formulario con un method="dialog" establece el returnValue en el name, si corresponde, del botón de envío que se usó para enviar el formulario. Si hubiéramos escrito <button type="submit" name="toasty">close</button>, el returnValue sería toasty.

Cuando se abre un diálogo, está presente el atributo booleano open, lo que significa que el diálogo está activo y se puede interactuar con él. Cuando se abre un diálogo agregando el atributo open en lugar de hacerlo a través de .show() o .showModal(), el diálogo no será modal. La propiedad HTMLDialogElement.open muestra true o false, según si el diálogo está disponible para la interacción, no si es modal o no.

Si bien JavaScript es el método preferido para abrir un diálogo, incluir el atributo open en la carga de la página y, luego, quitarlo con .close(), puede ayudar a garantizar que el diálogo esté disponible incluso cuando JavaScript no lo esté.

Detalles adicionales

No uses tabindex

El elemento que se activa para abrir el diálogo y el botón de cierre que contiene (y posiblemente otro contenido) pueden recibir enfoque y son interactivos. El elemento <dialog> no es interactivo y no recibe enfoque. No agregues la propiedad tabindex al diálogo.

Roles de ARIA

El rol implícito es dialog. Si el diálogo es una ventana de confirmación que comunica un mensaje importante que requiere una confirmación o alguna otra respuesta del usuario, establece role="alertdialog". El diálogo también debe tener un nombre accesible. Si el texto visible puede proporcionar el nombre accesible, agrega aria-labelledby="idOfLabelingText".

Valores predeterminados de CSS

Ten en cuenta que los navegadores proporcionan un diseño predeterminado para dialog. Firefox, Chrome y Edge establecen color: CanvasText; background-color: Canvas; y Safari establece color: black; background-color: white; en sus hojas de estilo de usuario-agente. El color se hereda de dialog y no de body o :root, lo que puede ser inesperado. La propiedad background-color no se hereda.

Verifica tu comprensión

Pon a prueba tus conocimientos sobre el elemento de diálogo.

¿Cómo se aplica diseño al área detrás del diálogo?

Con el pseudoelemento ::background.
Vuelve a intentarlo.
Con el pseudoelemento ::backdrop.
Correcto.
Con la propiedad background.
Vuelve a intentarlo.