小编典典

在附加元素上触发CSS过渡

css

正如这个问题所观察到的,新添加的元素上的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。

  • 为什么忽略附加元素上的即时CSS动画?
  • 这些方法如何以及为什么起作用?
  • 还有其他方法吗
  • 哪个是首选解决方案?

阅读 408

收藏
2020-05-16

共1个答案

小编典典

不激活新添加的元素的动画的原因是浏览器的批量重排。

当添加元素时,需要回流。添加类也是如此。但是,当您在 单个javascript循环中
同时进行这两个操作时,浏览器会抓住机会优化第一个。在这种情况下,只有一个(同时是初始和最终)样式值,因此不会发生过渡。

这个setTimeout技巧行得通,因为它延迟了类向另一轮javascript的添加,因此呈现给渲染引擎的值有两个,需要计算,因为有时间点,第一个值呈现给用户时。

批处理规则还有另一个例外。如果您尝试访问即时值,浏览器需要计算它。这些值之一是offsetWidth。当您访问它时,将触发重排。在实际显示期间,另外一个是单独完成的。同样,我们有两个不同的样式值,因此我们可以及时对它们进行插值。

实际上,这是极少数需要这种行为的情况之一。在大多数情况下,在DOM修改之间访问引起回流的属性可能会导致严重的速度下降。

首选的解决方案可能因人而异,但是对我来说,offsetWidth(或getComputedStyle())的访问是最好的。在某些情况下,当setTimeout被解雇时,它们之间不会重新计算样式。这种情况很少见,大多数情况是在加载的网站上发生的,但是这种情况确实发生了。这样一来,您将无法获得动画。通过访问任何计算出的样式,您将强制浏览器进行实际计算。

2020-05-16