Cuadro de diálogo

Un diálogo modal es un tipo especial de cuadro emergente que interrumpe al usuario en una página web. Si bien existen algunos casos de uso válidos para mostrar un diálogo emergente, debes tener mucho cuidado antes de agregar uno. Los diálogos modales obligan a los usuarios a enfocarse en contenido específico y a ignorar temporalmente el resto de la página.

Los diálogos pueden ser de los siguientes tipos:

  • Modal: Los usuarios solo pueden interactuar con el contenido dentro del diálogo. Los diálogos modales se muestran sobre el contenido de la página. La página se establece como inerte y, de forma predeterminada, se oculta con un fondo semitransparente.
  • No modal: Los usuarios pueden interactuar con el contenido fuera del diálogo.

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

Echa un vistazo a un ejemplo de un modal <dialog>. Haz clic en Abrir diálogo modal. Una vez abierto, hay tres formas de cerrar el diálogo: la tecla de escape, el envío de un formulario con un botón que tenga el atributo formmethod="dialog" establecido (o si el formulario tiene establecido el atributo 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ó con el método HTMLDialogElement.showModal(), es un diálogo modal. Cuando se abre un diálogo modal, se desactiva y se oculta todo lo que no sea el diálogo en sí. Cuando colocas el cursor sobre la IU fuera del diálogo, todos los elementos se comportan como si se hubiera establecido pointer-events: none;. Incluso el botón que abre el diálogo no reaccionará a las interacciones.

Cuando se abre el cuadro de diálogo, el enfoque se mueve hacia él. 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 varias veces, solo el contenido dentro del diálogo puede recibir el foco mientras el modal está abierto. Todo lo que está fuera del modal permanece inerte.

Cuando se cierra un diálogo, modal o no, el enfoque vuelve al elemento que lo abrió. Evita abrir un diálogo de manera programática sin una acción del usuario. Si es necesario, asegúrate de devolver el enfoque al lugar donde estaba antes de que se abriera el diálogo, en especial si el usuario lo descarta sin interactuar con él.

Existe un atributo global inert que se puede usar para inhabilitar un elemento y todos sus descendientes, excepto cualquier diálogo activo. Cuando se abre un diálogo modal con showModal(), la inercia o la desactivación se producen de forma predeterminada. El atributo no se establece de forma explícita.

Se puede aplicar diseño al fondo que oculta todo lo que no sea el diálogo 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 mira 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

El HTMLDialogElement.show() también abre un diálogo, pero sin agregar un fondo ni hacer que nada se vuelva inerte. La tecla de escape solo cierra los diálogos modales, no los no modales. Por este motivo, es aún más importante incluir un método para cerrar el diálogo no modal. Si la opción de cierre está fuera del diálogo, el foco volverá al elemento que abrió el diálogo. Esta no es una experiencia del usuario ideal.

Si bien la especificación no requiere oficialmente un botón para cerrar el diálogo, considéralo obligatorio. Un botón visible que puede recibir el foco 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 estableciendo method="dialog" en el <form> o formmethod="dialog" en el botón.

Cuando un usuario envía datos con el método dialog, se mantiene el estado de los datos que ingresó. Mientras haya un evento de envío, el formulario pasará por la validación de restricciones (a menos que se establezca novalidate). Los datos del usuario no se borran ni se envían. Puedes crear un botón de cierre sin JavaScript:

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

Es posible que hayas notado el atributo autofocus establecido en el <button> de cierre en este ejemplo. Los elementos con el atributo autofocus establecido dentro de un <dialog> solo reciben el enfoque en la carga de la página si esta ya se cargó con el diálogo visible. Si la página no se cargó, estos elementos reciben el foco cuando se abre el diálogo.

Cuando se abre un diálogo, el primer elemento enfocable dentro del diálogo recibe el foco, a menos que un elemento diferente tenga establecido el atributo autofocus. Establecer 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 el módulo de enfoque.

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

Cuando se abre un diálogo, el atributo booleano open está presente, 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 .show() o .showModal(), el diálogo no es modal. La propiedad HTMLDialogElement.open devuelve 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 el enfoque y son interactivos. El elemento <dialog> no es interactivo y no recibe el 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 que requiere una respuesta o confirmación del usuario, establece role="alertdialog". Incluye un nombre de accesibilidad para el diálogo. Si el texto visible puede proporcionar el nombre de accesibilidad, agrega aria-labelledby="idOfLabelingText".

Valores predeterminados de CSS

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

Verifica tus conocimientos

Pon a prueba tus conocimientos sobre el elemento dialog.

¿Cómo se aplica estilo 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.