@starting-style + transition-behavior: allow-discrete

Baseline 2024 (Chrome 117, Safari 17.5, Firefox 129).

Chrome 117Edge 117Safari 17.5Firefox 129

Permite transicionar desde `display:none` y otras propiedades discretas. `@starting-style` define los valores "antes del primer render" para que funcionen las animaciones de entrada; `allow-discrete` mantiene el elemento visible hasta que termina la transición de salida.

Saved. Click anywhere to dismiss.
CSS
.fx-014{
  inset:auto 16px 16px auto;background:#111;color:#fff;padding:12px 16px;border:0;border-radius:10px;font-family:system-ui;
  opacity:0;translate:0 16px;
  transition:opacity .25s,translate .25s,display .25s allow-discrete,overlay .25s allow-discrete;
}
.fx-014:popover-open{opacity:1;translate:0 0}
@starting-style{.fx-014:popover-open{opacity:0;translate:0 16px}}
.fx-014 :is(a,button,input,select,textarea):focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
HTML
<button popovertarget="fx-014-toast">Show toast</button>
<div id="fx-014-toast" popover class="fx-014">Saved. Click anywhere to dismiss.</div>

Fallback: Los navegadores sin soporte muestran y ocultan al instante; el popover sigue funcionando.

Fuente: developer.mozilla.org/en-US/docs/Web/CSS/@starting-style

Prompt

Para animaciones de entrada y salida de elementos que alternan `display`, no uses temporización de clases en JS. Define el estado visible de forma normal, pon los valores ocultos iniciales en `@starting-style { .el:open {...} }` para la entrada, e incluye `display .3s allow-discrete` (más `overlay` para elementos de la capa superior) en la lista de transiciones para que la animación de salida pueda reproducirse antes de que el elemento desaparezca.