在附加元素上触发 CSS 转换 [英] Trigger CSS transition on appended element

查看:31
本文介绍了在附加元素上触发 CSS 转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如 这个问题 所观察到的,新的 CSS 转换立即-附加的元素以某种方式被忽略 - 转换的结束状态立即呈现.

例如,给定这个 CSS(这里省略了前缀):

.box {不透明度:0;过渡:全2s;背景颜色:红色;高度:100px;宽度:100px;}.box.in { 不透明度:1;}

此元素的不透明度将立即设置为 1:

//不动画var $a = $('

').addClass('box a').appendTo('#wrapper');$a.addClass('in');

我已经看到了几种触发转换以获得预期行为的方法:

//是否动画var $b = $('

').addClass('box b').appendTo('#wrapper');设置超时(功能(){$('.b').addClass('in');},0);//是否动画var $c = $('

').addClass('box c').appendTo('#wrapper');$c[0].offsetWidth = $c[0].offsetWidth$c.addClass('in');//是否动画var $d = $('

').addClass('box d').appendTo('#wrapper');$d.focus().addClass('in');

同样的方法适用于 vanilla JS DOM 操作 - 这不是特定于 jQuery 的行为.

编辑 - 我使用的是 Chrome 35.

JSFiddle(包括原生 JS 示例).

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

解决方案

未对新添加的元素进行动画处理的原因是浏览器批处理回流.

添加元素时,需要回流.这同样适用于添加类.但是,当您在单个 javascript 回合中同时执行这两项操作时,浏览器会抓住机会优化第一个.在这种情况下,只有一个(同时为初始和最终)样式值,因此不会发生转换.

setTimeout 技巧有效,因为它延迟了将类添加到另一轮 javascript 中,因此渲染引擎需要计算两个值,因为存在时间点,当第一个呈现给用户时.

批处理规则还有一个例外.如果您尝试访问它,浏览器需要计算立即值.这些值之一是 offsetWidth.当您访问它时,会触发回流.另一个是在实际显示过程中单独完成的.同样,我们有两个不同的样式值,因此我们可以及时插入它们.

这确实是极少数需要这种行为的场合之一.大多数情况下,在 DOM 修改之间访问导致回流的属性会导致严重的减速.

首选方案可能因人而异,但对我来说,offsetWidth(或getComputedStyle())的访问是最好的.在某些情况下,当 setTimeout 被触发时,中间没有重新计算样式.这种情况很少见,主要是在加载的网站上,但它会发生.那么你将不会得到你的动画.通过访问任何计算出的样式,您将强制浏览器实际计算它.

As this question observes, immediate CSS transitions on newly-appended elements are somehow ignored - the end state of the transition is rendered immediately.

For example, given this CSS (prefixes omitted here):

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

.box.in { opacity: 1; }

The opacity of this element will be set immediately to 1:

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

I have seen several ways of triggering the transition to get the expected behaviour:

// 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');

The same methods apply to vanilla JS DOM manipulation - this is not jQuery-specific behaviour.

Edit - I am using Chrome 35.

JSFiddle (includes vanilla JS example).

  • Why are immediate CSS animations on appended elements ignored?
  • How and why do these methods work?
  • Are there other ways of doing it
  • Which, if any, is the preferred solution?

解决方案

The cause of not animating the newly added element is batching reflows by browsers.

When element is added, reflow is needed. The same applies to adding the class. However when you do both in single javascript round, browser takes its chance to optimize out the first one. In that case, there is only single (initial and final at the same time) style value, so no transition is going to happen.

The setTimeout trick works, because it delays the class addition to another javascript round, so there are two values present to the rendering engine, that needs to be calculated, as there is point in time, when the first one is presented to the user.

There is another exception of the batching rule. Browser need to calculate the immediate value, if you are trying to access it. One of these values is offsetWidth. When you are accessing it, the reflow is triggered. Another one is done separately during the actual display. Again, we have two different style values, so we can interpolate them in time.

This is really one of very few occasion, when this behaviour is desirable. Most of the time accessing the reflow-causing properties in between DOM modifications can cause serious slowdown.

The preferred solution may vary from person to person, but for me, the access of offsetWidth (or getComputedStyle()) is the best. There are cases, when setTimeout is fired without styles recalculation in between. This is rare case, mostly on loaded sites, but it happens. Then you won't get your animation. By accessing any calculated style, you are forcing the browser to actually calculate it.

这篇关于在附加元素上触发 CSS 转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆