正如这个问题所观察到的,新添加的元素上的CSS过渡立即被忽略了-过渡的结束状态立即被呈现。
例如,给定此CSS(此处省略前缀):
.box { opacity: 0; transition: all 2s; background-color: red; height: 100px; width: 100px; } .box.in { opacity: 1; }
此元素的不透明度将立即设置为1:
// Does not animate var $a = $('<div>') .addClass('box a') .appendTo('#wrapper'); $a.addClass('in');
我已经看到了触发过渡以获得预期行为的几种方法:
// 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');
相同的方法适用于原始JS DOM操作-这不是jQuery特定的行为。
编辑-我正在使用Chrome 35。
不激活新添加的元素的动画的原因是浏览器的批量重排。
当添加元素时,需要回流。添加类也是如此。但是,当您在 单个javascript循环中 同时进行这两个操作时,浏览器会抓住机会优化第一个。在这种情况下,只有一个(同时是初始和最终)样式值,因此不会发生过渡。
这个setTimeout技巧行得通,因为它延迟了类向另一轮javascript的添加,因此呈现给渲染引擎的值有两个,需要计算,因为有时间点,第一个值呈现给用户时。
setTimeout
批处理规则还有另一个例外。如果您尝试访问即时值,浏览器需要计算它。这些值之一是offsetWidth。当您访问它时,将触发重排。在实际显示期间,另外一个是单独完成的。同样,我们有两个不同的样式值,因此我们可以及时对它们进行插值。
offsetWidth
实际上,这是极少数需要这种行为的情况之一。在大多数情况下,在DOM修改之间访问引起回流的属性可能会导致严重的速度下降。
首选的解决方案可能因人而异,但是对我来说,offsetWidth(或getComputedStyle())的访问是最好的。在某些情况下,当setTimeout被解雇时,它们之间不会重新计算样式。这种情况很少见,大多数情况是在加载的网站上发生的,但是这种情况确实发生了。这样一来,您将无法获得动画。通过访问任何计算出的样式,您将强制浏览器进行实际计算。
getComputedStyle()