Tema representativo de entrevista

Entrevista de Frontend: ¿Cómo se utiliza transition-behavior para estados discretos de la interfaz de usuario?

FrontendIntermedio
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

¿Por qué display: none no puede realizar una transición suave por sí mismo? Diseñe una entrada y salida compatible para un popover utilizando transition-behavior.

1. Contexto y planteamiento

Un diálogo está oculto con display: none. El equipo de producto desea que aparezca y desaparezca con un efecto de desvanecimiento (fade in/out), saliendo del layout únicamente después de la animación. El equipo solo aplica una transición a opacity, por lo que la entrada no tiene una animación visible y la salida desaparece de inmediato. Explique las propiedades discretas, diseñe el CSS y aborde el fallback para navegadores, la gestión del foco y prefers-reduced-motion.

2. Lo que evalúa el entrevistador

  • Si sabe que las propiedades discretas como display y content-visibility no tienen valores intermedios continuos.
  • Si puede utilizar transition-behavior: allow-discrete o la propiedad abreviada (shorthand) correctamente en lugar de tratarla como una duración.
  • Si comprende que el momento del cambio (flip timing) difiere entre la entrada y la salida, y que @starting-style establece un estilo inicial.
  • Si incluye compatibilidad, accesibilidad, foco, reducción de movimiento (reduced motion) y pruebas reales de renderizado.

3. Preguntas aclaratorias antes de responder

  1. ¿Es un elemento normal, un diálogo nativo o un popover del top-layer?
  2. ¿Debe salir del layout y volverse no enfocable, o basta con omitir el repintado (paint)?
  3. ¿Qué versiones de navegador se admiten y cuál es el fallback sin transiciones discretas?
  4. ¿Cómo deben comportarse el foco, la tecla Escape, los clics en el backdrop y las preferencias de reducción de movimiento durante la animación?

4. Estructura de respuesta en 30 segundos

display es discreto, por lo que no interpola de forma predeterminada. Utilice transition-behavior: allow-discrete para habilitarlo en una transición y proporcione también una duración distinta de cero para opacity o transform. En la entrada, cambie a un valor visible con la suficiente antelación para toda la animación; en la salida, mantenga el elemento visible hasta el final. Utilice @starting-style para el primer fotograma insertado. Los navegadores más antiguos pueden ignorar la mejora manteniendo el fallback continuo; el foco, la semántica de ocultación y el movimiento reducido aún requieren un manejo explícito.

5. Respuesta detallada paso a paso

Paso 1: Separar las propiedades continuas y discretas

opacity y transform pueden producir valores intermedios continuos; display solo alterna entre valores. Sin allow-discrete, el navegador cambia display inmediatamente, por lo que un elemento que se cierra se elimina antes de que se pueda ver su transición de opacidad y un elemento que se abre no tiene un fotograma inicial visible. transition-behavior solo permite la transición discreta; transition-property y un transition-duration distinto de cero siguen siendo necesarios.

Paso 2: Construir una transición de panel bidireccional

Declare primero el fallback continuo y luego una declaración mejorada con allow-discrete. Durante la salida, display debe cambiar cerca del 100% para que el contenido permanezca visible; durante la entrada debe cambiar a un valor visible de forma temprana. No declare únicamente transition-behavior olvidando la opacidad de destino o el estado de transformación.

css
.panel {
  opacity: 0;
  transform: translateY(-0.5rem);
  display: none;
  transition: opacity 180ms ease, transform 180ms ease;
  transition: opacity 180ms ease, transform 180ms ease, display 180ms allow-discrete;
}

.panel[data-open="true"] {
  opacity: 1;
  transform: translateY(0);
  display: block;
}

Paso 3: Manejar la primera entrada y los popovers

Cuando un elemento se inserta dinámicamente o un popover se abre por primera vez, puede que no haya un estilo visible previo con el que comparar. @starting-style proporciona la opacidad y transformación iniciales. Un popover nativo también entra en la capa superior (top layer), por lo que display y overlay deben incluirse en la transición discreta o el elemento que sale se eliminará inmediatamente. Pruebe la combinación en las versiones de navegadores de destino.

Paso 4: Diseñar el fallback y la detección de características

Los navegadores más antiguos ignoran el valor desconocido allow-discrete, pero aun así deben mantener la transición base de opacidad/transformación. Coloque las reglas de mejora detrás de @supports (transition-behavior: allow-discrete) si es necesario, en lugar de ocultar todo el estilo base. El fallback aún debe abrirse, cerrarse, recibir foco y exponer la semántica de ocultación correcta.

Paso 5: Accesibilidad, rendimiento y verificación

La animación no es el estado de accesibilidad. Al cerrarse, sincronice hidden, aria-hidden o el estado nativo del diálogo y devuelva el foco al elemento desencadenante (trigger); al abrirse, mueva el foco hacia el interior y admita la tecla Escape. Reduzca o elimine la duración bajo prefers-reduced-motion: reduce. Pruebe el layout, el repintado (paint), el foco por teclado, los lectores de pantalla, las alternancias rápidas, las transiciones interrumpidas y el costo de layout/composición en dispositivos de gama baja.

6. Ejemplo de una respuesta de alta calidad

display es discreto y no tiene un valor intermedio continuo como la opacidad. Mantendría una transición base de opacidad/transformación, y luego habilitaría display en la ruta mejorada con transition-behavior: allow-discrete; la entrada cambia a visible de manera temprana, mientras que la salida permanece visible hasta el final. @starting-style proporciona el primer fotograma, y los popovers también necesitan manejo de display y overlay en la capa superior. Los navegadores antiguos ignoran la mejora pero conservan la animación base. También sincronizaría el foco, la tecla Escape, la semántica oculta y la reducción de movimiento, para luego verificar el comportamiento en todos los navegadores y flujos de teclado.

7. Errores comunes

  • Aplicar transición solo a la opacidad → display cambia inmediatamente → agregue allow-discrete manteniendo una propiedad continua.
  • Tratar transition-behavior como una duración → la propiedad discreta sigue sin realizar la transición → declare la propiedad y también una duración distinta de cero.
  • Cambiar display a none al inicio de la salida → el desvanecimiento no se puede ver → alinee el cambio discreto con el final de la duración de salida.
  • Ignorar la primera inserción → la primera apertura no tiene animación de entrada → defina un fotograma inicial con @starting-style.
  • Probar solo con mouse y navegadores modernos → los estados de teclado, lectores de pantalla o fallback fallan → incluya verificaciones de supports, fallback, foco y reducción de movimiento.

8. Preguntas de seguimiento y respuestas

¿Por qué display debería cambiar al final de la salida?

Si cambia a none de inmediato, el elemento abandona el layout y el renderizado, por lo que no hay contenido visible durante el resto de la duración de la opacidad. Manténgalo visible cerca del 100% y luego pase al estado oculto.

¿allow-discrete interpola display en cada fotograma?

No. Permite que un valor discreto participe en una transición, pero el valor aún cambia en un punto definido. El cambio visual continuo proviene de la opacidad, transformación u otra propiedad interpolable.

¿Cómo mantener utilizables los navegadores más antiguos?

Declare primero la transición base sin allow-discrete y luego mejórela con @supports o una declaración posterior. Si la mejora no está disponible, acepte un cambio instantáneo de display preservando al mismo tiempo el comportamiento de los botones, el foco y la semántica oculta.

¿Cómo manejar la reducción de movimiento (reduced motion)?

Bajo prefers-reduced-motion: reduce, reduzca la duración sustancialmente o configúrela en cero mientras mantiene la sincronización de estado, el movimiento del foco y los controles de cierre. No se limite a ocultar la animación dejando un elemento enfocable invisible.

Fuentes públicas

Preguntas relacionadas