section div attribute javascript css css3 dom

javascript - div - Desencadenar la transición de CSS en el elemento adjunto



section html (6)

A diferencia de Brendan , encontré que requestAnimationFrame() funcionaba en Chrome 63, Firefox 57, IE11 y Edge.

var div = document.createElement("div"); document.body.appendChild(div); requestAnimationFrame(function () { div.className = "fade"; });

div { height: 100px; width: 100px; background-color: red; } .fade { opacity: 0; transition: opacity 2s; }

Como esta pregunta observa, las transiciones de CSS inmediatas sobre los elementos recién añadidos se ignoran de alguna manera: el estado final de la transición se representa de inmediato.

Por ejemplo, dado este CSS (prefijos omitidos aquí):

.box { opacity: 0; transition: all 2s; background-color: red; height: 100px; width: 100px; } .box.in { opacity: 1; }

La opacidad de este elemento se establecerá inmediatamente en 1:

// Does not animate var $a = $(''<div>'') .addClass(''box a'') .appendTo(''#wrapper''); $a.addClass(''in'');

He visto varias maneras de activar la transición para obtener el comportamiento esperado:

// Does animate var $b = $(''<div>'') .addClass(''box b'') .appendTo(''#wrapper''); setTimeout(function() { $(''.b'').addClass(''in''); },0); // Does animate var $c = $(''<div>'') .addClass(''box c'') .appendTo(''#wrapper''); $c[0]. offsetWidth = $c[0].offsetWidth $c.addClass(''in''); // Does animate var $d = $(''<div>'') .addClass(''box d'') .appendTo(''#wrapper''); $d.focus().addClass(''in'');

Los mismos métodos se aplican a la manipulación vanilla JS DOM: esto no es un comportamiento específico de jQuery.

Editar - Estoy usando Chrome 35.

JSFiddle (incluye el ejemplo JS vanilla).

  • ¿Por qué se ignoran las animaciones CSS inmediatas en los elementos adjuntos?
  • ¿Cómo y por qué funcionan estos métodos?
  • ¿Hay otras formas de hacerlo
  • ¿Cuál, si hay alguna, es la solución preferida?

En lugar de tratar de forzar un repintado inmediato o un cálculo de estilo, intenté usar requestAnimationFrame() para permitir que el navegador pintara en su siguiente marco disponible.

En Chrome + Firefox, el navegador optimiza la representación demasiado, por lo que todavía no ayuda (funciona en Safari).

Me decidí a forzar manualmente un retraso con setTimeout() luego usando requestAnimationFrame() para dejar que el navegador pintara de manera responsable. Si el apéndice no se ha pintado antes de que finalice el tiempo de espera, se puede ignorar la animación, pero parece funcionar de manera confiable.

setTimeout(function () { requestAnimationFrame(function () { // trigger the animation }); }, 20);

Elegí 20 ms porque es más grande que 1 fotograma a 60 fps (16,7 g) y algunos navegadores no registran tiempos de espera <5 ms.

Cruzar los dedos para obligar a la animación a comenzar en el siguiente cuadro y luego iniciarlo de manera responsable cuando el navegador esté listo para pintar nuevamente.


La causa de no animar el elemento recién agregado es los reflujos por lotes de los navegadores.

Cuando se agrega un elemento, se necesita reflujo. Lo mismo aplica para agregar la clase. Sin embargo, cuando haces ambas cosas en una sola ronda de javascript , el navegador aprovecha para optimizar la primera. En ese caso, solo hay un valor de estilo único (inicial y final al mismo tiempo), por lo que no se realizará ninguna transición.

El truco de setTimeout funciona, porque retrasa la adición de clase a otra ronda de javascript, por lo que hay dos valores presentes en el motor de representación, que deben calcularse, ya que hay un punto en el tiempo, cuando el primero se presenta al usuario.

Hay otra excepción de la regla de procesamiento por lotes. El navegador necesita calcular el valor inmediato, si está intentando acceder a él. Uno de estos valores es offsetWidth . Cuando está accediendo a él, se activa el reflujo. Otro se hace por separado durante la visualización real. De nuevo, tenemos dos valores de estilo diferentes, por lo que podemos interpolarlos en el tiempo.

Esta es realmente una de muy pocas ocasiones, cuando este comportamiento es deseable. La mayoría de las veces, el acceso a las propiedades de reflujo entre las modificaciones DOM puede causar una desaceleración grave.

La solución preferida puede variar de persona a persona, pero para mí, el acceso de offsetWidth (o getComputedStyle() ) es el mejor. Hay casos en que setTimeout se setTimeout sin el recálculo de estilos en el medio. Este es un caso raro, principalmente en sitios cargados, pero sucede. Entonces no obtendrás tu animación. Al acceder a cualquier estilo calculado, está forzando al navegador a calcularlo realmente.


La solución de @ Frizi funciona, pero a veces he encontrado que getComputedStyle no ha funcionado cuando cambio ciertas propiedades en un elemento. Si eso no funciona, puedes probar getBoundingClientRect() siguiente manera, que he encontrado que es a prueba de balas:

Supongamos que tenemos un elemento el , en el que queremos transitar la opacity , pero el es display:none; opacity: 0 display:none; opacity: 0 :

el.style.display = ''block''; el.style.transition = ''opacity .5s linear''; // reflow el.getBoundingClientRect(); // it transitions! el.style.opacity = 1;


Usando jQuery prueba esto ( Un ejemplo aquí ):

var $a = $(''<div>'') .addClass(''box a'') .appendTo(''#wrapper''); $a.css(''opacity''); // added $a.addClass(''in'');

Usando la versión javaScript de Vanilla prueba esto:

var e = document.createElement(''div''); e.className = ''box e''; document.getElementById(''wrapper'').appendChild(e); window.getComputedStyle(e).opacity; // added e.className += '' in'';

Breve idea:

El getComputedStyle() todos los cambios de estilo pendientes y fuerza al motor de diseño a calcular el estado actual del elemento, por lo tanto .css() funciona de manera similar.

Acerca de css() desde el sitio de jQuery :

El método .css () es una forma conveniente de obtener una propiedad de estilo del primer elemento coincidente, especialmente a la luz de las diferentes maneras en que los navegadores acceden a la mayoría de esas propiedades (el método getComputedStyle() () en navegadores basados ​​en estándares versus el estilo currentStyle y runtimeStyle propiedades en Internet Explorer) y los diferentes términos que usan los navegadores para ciertas propiedades.

Puede usar getComputedStyle()/css() lugar de setTimeout . También puede leer este artículo para obtener información detallada y ejemplos.


Utilice el siguiente código, use "focus ()"

Jquery

var $a = $(''<div>'') .addClass(''box a'') .appendTo(''#wrapper''); $a.focus(); // focus Added $a.addClass(''in'');

Javascript

var e = document.createElement(''div''); e.className = ''box e''; document.getElementById(''wrapper'').appendChild(e).focus(); // focus Added e.className += '' in'';