En HTML5 es posible crear ventanas de diálogo personalizadas sin necesidad de Javascript (o mediante muy poco Javascript), de forma nativa, e incluso crear ventanas modales. Todo ello, se realizará mediante la etiqueta HTML <dialog> en diferentes modalidades:

  • Ventana de diálogo: Se denomina así a una ventana que comunica el sistema o máquina con el usuario, para anunciarle información y pedirle confirmación, para pedirle datos, etc.

  • Ventana de diálogo modal: Se denomina así a una variación de la anterior, donde se obliga al usuario a atenderla y responderla, impidiendo hacer ninguna otra tarea mientras.

La etiqueta <dialog>

A partir de HTML5.1, se incorpora una etiqueta <dialog> mediante la cuál podemos construir nuestras propias ventanas de diálogo personalizadas. Dichas ventanas pueden contener toda la información HTML que queramos: texto, imágenes, botones, video o cualquier otra cosa, y ser personalizada mediante CSS.

Un ejemplo básico podría ser el siguiente:

<dialog open>
  <p>Esto es un ejemplo de mensaje de diálogo.</p>
</dialog>

Al igual que vimos en la etiqueta <details>, la etiqueta <dialog> tiene un atributo open que de no establecerlo, se considera que la ventana de diálogo está cerrada (tiene un display: none de CSS por defecto), por lo que no se muestra.

Como puedes ver, la forma de crear ventanas de diálogo es muy sencilla. En el interior de <dialog> puedes indicar toda la información que queramos mostrar en la ventana:

<dialog open>
  <p>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="#888888" d="M11 9h2V7h-2m1 13c-4.41 0-8-3.59-8-8s3.59-8
        8-8s8 3.59 8 8s-3.59 8-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10
        10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m-1 15h2v-6h-2v6Z" />
    </svg>
    Esto es un ejemplo de mensaje de diálogo.
  </p>
  <button>Aceptar</button>
</dialog>
svg {
  vertical-align: bottom;
}

Además, aunque la etiqueta <dialog> ya tiene un CSS mínimo para que se vea bien, mediante CSS podemos darle estilo como a cualquier otro elemento HTML, convirtiendo nuestra ventana de diálogo en algo más bonito de lo que viene por defecto, aplicando colores de borde, fondo, gradientes, sombras y otros detalles.

Pero el botón de Aceptar no hace nada de momento. Vamos a solucionarlo.

Cerrar el <dialog>

Una ventana de diálogo que no se puede cerrar no tiene sentido, así que vamos a analizar dos formas de interactuar con ella y cerrarla. Las primeras, sin utilizar Javascript, y la última, utilizando Javascript.

El siguiente ejemplo es exactamente igual al anterior, sólo que hemos envuelto el <button> en una etiqueta <form> con el atributo method="dialog", que es el que hace la magia. Si se pulsa ese botón, el form buscará el diálogo padre y lo cerrará... ¡Sin necesidad de Javascript!

<dialog open>
  <p>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="#888888" d="M11 9h2V7h-2m1 13c-4.41 0-8-3.59-8-8s3.59-8
        8-8s8 3.59 8 8s-3.59 8-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10
        10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m-1 15h2v-6h-2v6Z" />
    </svg>
    Esto es un ejemplo de mensaje de diálogo.
  </p>
  <form method="dialog">
    <button>Aceptar</button>
  </form>
</dialog>
svg {
  vertical-align: bottom;
}

Como veremos más adelante, también podemos usar un atributo formmethod en el <button>, en lugar de utilizar el atributo method en el <form>.

Además, también podemos utilizar el atributo closedby en el elemento <dialog> para indicar que se puede cerrar la ventana de diálogo en ciertas situaciones adicionales. En este ejemplo además puedes cerrar la ventana pulsando ESC o haciendo clic fuera de la ventana:

<dialog open closedby="any">
  <p>
    <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24">
      <path fill="#888888" d="M11 9h2V7h-2m1 13c-4.41 0-8-3.59-8-8s3.59-8
        8-8s8 3.59 8 8s-3.59 8-8 8m0-18A10 10 0 0 0 2 12a10 10 0 0 0 10
        10a10 10 0 0 0 10-10A10 10 0 0 0 12 2m-1 15h2v-6h-2v6Z" />
    </svg>
    Esto es un ejemplo de mensaje de diálogo.
  </p>
  <form method="dialog">
    <button>Aceptar</button>
  </form>
</dialog>
svg {
  vertical-align: bottom;
}

En el ejemplo hemos utilizado any como valor, pero podemos utilizar otras:

ValorDescripción
anyPermite cerrar la ventana pulsando fuera de la ventana o con peticiones como pulsar ESC.
closerequestPermite cerrar la ventana con peticiones como pulsar ESC.
noneNo permite cerrar la ventana automáticamente.

Sin embargo, podemos utilizar Javascript para cerrar la ventana de diálogo o incluso darle funcionalidad más avanzada. Observa el siguiente ejemplo. Comprobarás que no aparece nada (es normal, sigue leyendo):

<dialog id="alert-dialog">
  <p>Esto es un ejemplo de mensaje de diálogo.</p>
  <button onClick="this.parentElement.close()">Aceptar</button>
</dialog>

En este fragmento de código hemos añadido varios detalles:

  • La etiqueta <dialog> tiene un id para identificarla posteriormente.
  • La etiqueta <dialog> no tiene atributo open por lo que estará oculta por defecto.
  • Al <button> del diálogo, le hemos puesto un evento onClick
  • En el evento onClick:
    • Con this hacemos referencia a ese elemento: <button>
    • Con this.parentElement hacemos referencia al elemento padre: <dialog>
    • Por lo tanto, ejecutamos el método .close() del <dialog> y lo cerramos

Pero aún no aparece nada en el navegador. Esto ocurre porque el <dialog> no tiene el atributo open. Añadimos otro botón externo con el id con valor show-button. Mediante Javascript, vamos a darle funcionalidad a este botón para que abra la ventana de diálogo:

<dialog id="alert-dialog">
  <p>Esto es un ejemplo de mensaje de diálogo.</p>
  <button onClick="this.parentElement.close()">Aceptar</button>
</dialog>

<button id="show-button">Mostrar diálogo</button>
const showButton = document.querySelector("#show-button");
showButton.addEventListener("click", function () {
  const alertDialog = document.querySelector("#alert-dialog");
  alertDialog.show();
});

En este caso, estamos localizando el botón con id a #show-button y escuchando los eventos de click sobre él. Cuando ocurra alguno, localizamos la ventana de diálogo con id a #alert-dialog y la mostramos ejecutando el método .show().

Diálogos modales

Como hemos comentado anteriormente, una ventana modal es un tipo de ventana que se muestra al usuario, generalmente, para avisarle de algo o pedirle una información necesaria para continuar. Se caracteriza en que una vez se muestra, no se le permite interactuar con cualquier otro elemento de la página hasta que atienda el mensaje de esa ventana modal.

Para crear una ventana modal con la etiqueta <dialog> usaremos exactamente el mismo código anterior, sólo tendremos que cambiar el método .show() por .showModal(). Observa que también hemos vuelto a usar el <form> como padre del <button> para cerrar el diálogo sin Javascript, sólo que en esta ocasión hemos utilizado un atributo formmethod que permite sobreescribir el method del <form> padre:

<dialog id="alert-dialog">
  <h3>¡Vuelve a la sombra!</h3>
  <img src="gandalf.jpg" alt="Gandalf">
  <p>¡NO... PUEDES... PASAR!</p>
  <form>
    <button formmethod="dialog">Ok!</button>
  </form>
</dialog>

<button id="show-button">Mostrar diálogo</button>
body {
  min-height: 500px;
}
const showButton = document.querySelector("#show-button");
showButton.addEventListener("click", function () {
  const alertDialog = document.querySelector("#alert-dialog");
  alertDialog.showModal();
});

Esto nos permitiría mostrar una ventana modal, que tiene algunas diferencias con el ejemplo anterior de la ventana de diálogo no modal:

Diferencias:

  • Por defecto, el fondo se oscurece un poco.
  • La ventana se suele centrar también verticalmente, para centrar la atención en ella.
  • Sólo puede haber una ventana modal, ventanas normales pueden existir varias.
  • La más importante: No deja interactuar con ningún otro elemento de la página.

Estilo CSS del modal

Existen varios mecanismos específicos para <dialog> para cambiar el estilo de las ventanas de diálogo o elementos relacionados:

NombreDescripción
:openDa estilo a la ventana de diálogo que está abierta (tiene el atributo open).
:closedDa estilo a la ventana de diálogo que está oculta (no tiene el atributo open).
::backdropDa estilo al fondo de la página cuando el diálogo está abierto.

Veamos algunos ejemplos.

Mediante las pseudoclases :open y :closed podemos dar estilo a una ventana de diálogo cuando está abierta o incluso cuando está oculta.

<dialog id="alert-dialog">
  <h3>¡Vuelve a la sombra!</h3>
  <form>
    <button formmethod="dialog">Ok!</button>
  </form>
</dialog>

<button id="show-button">Mostrar diálogo</button>
dialog:open {
  background: indigo;
  color: white;
}

dialog:closed {
  display: block;
  background: #333;
  color: #222;
  opacity: 0.5;
}
const showButton = document.querySelector("#show-button");
showButton.addEventListener("click", function () {
  const alertDialog = document.querySelector("#alert-dialog");
  alertDialog.show();
});

Ten en cuenta que una ventana de diálogo si no tiene el atributo open se considera oculta, por lo que tiene un display: none por defecto. Si quieres ver los estilos, tendrás que cambiar el valor del display.

Como curiosidad, la pseudoclase :open y :closed a parte de <dialog> también se puede utilizar para elementos HTML <details> y desplegables <select>.

Aunque el navegador ya nos muestra algunos cambios visuales en el fondo de una ventana modal, nosotros podemos hacer más cambios utilizando el pseudoelemnto CSS ::backdrop sobre la ventana de diálogo. De esta forma, podremos darle estilos al fondo de la ventana modal, y así enfatizar la importancia de nuestra ventana:

<button onClick="this.nextElementSibling.showModal()">Mostrar diálogo</button>

<dialog id="alert-dialog">
  <h3>¡Vuelve a la sombra!</h3>
  <img src="gandalf.jpg" alt="Gandalf">
  <p>¡NO... PUEDES... PASAR!</p>
  <button onClick="this.parentElement.close()">Ok!</button>
</dialog>
body {
  min-height: 500px;
}

#alert-dialog::backdrop {
  background: linear-gradient(#000d, #000a);
}

Observa que hemos establecido un fondo con un gradiente lineal CSS que va desde un color negro con cierta transparencia, hasta otra tonalidad de color negro con algo más de transparencia. Por supuesto, el desarrollador puede personalizar estos estilos a su gusto para que encajen con el diseño de la página o la situación correspondiente.

Animar la ventana modal

Es posible que nos interese realizar una animación de la ventana modal, de modo que en lugar de aparecer de repente, realice algún tipo de animación de entrada y/o de salida. Observa el ejemplo anterior, modificado para añadirle animación:

<button onClick="this.nextElementSibling.showModal()">Mostrar diálogo</button>

<dialog id="alert-dialog">
  <h3>¡Vuelve a la sombra!</h3>
  <img src="gandalf.jpg" alt="Gandalf">
  <p>¡NO... PUEDES... PASAR!</p>
  <form method="dialog">
    <button>Ok!</button>
  </form>
</dialog>
body {
  min-height: 500px;
}

#alert-dialog {
  opacity: 0;
  transition:
    display 1s allow-discrete,
    overlay 1s allow-discrete,
    translate 1s,
    opacity 1s;
  translate: 0 50%;
  will-change: translate, opacity;
}

#alert-dialog[open] {
  opacity: 1;
  translate: 0;
  @starting-style {
    opacity: 0;
    translate: 0 50%;
  }
}

#alert-dialog::backdrop {
  background: linear-gradient(#000d, #000a);
  opacity: 1;
  transition:
    display 1s allow-discrete,
    opacity 1s;

  @starting-style { opacity: 0 }
}

#alert-dialog:not([open])::backdrop {
  opacity: 0;
}

Hemos realizado los siguientes pasos:

  • 1️⃣ Por defecto, el <dialog> está transparente y desplazado hacia abajo.
  • 2️⃣ Añadimos transición para animar el estado del diálogo. Aquí overlay es clave.
  • 3️⃣ El @starting-style del [open] ayuda a realizar el inicio de la transición con suavidad.
  • 4️⃣ Lo usamos también en el ::backdrop para suavizar la transición de entrada.
  • 5️⃣ Utilizamos :not([open])::backdrop para suavizar la transición de salida.
  • 6️⃣ Usamos will-change para optimizar la animación.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev

Este sitio web es bloqueado en España cuando hay fútbol