为什么在设置属性后显示元素时隐藏元素时发生转移? [英] Why does a transition occur when showing an element after setting a property while the element is hidden?

查看:132
本文介绍了为什么在设置属性后显示元素时隐藏元素时发生转移?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里可以看到一个实例。



红色正方形(显示)位于绿色正方形正上方(隐藏为溢出)。点击正方形,两个彩色正方形立即变得完全透明。此外,红色正方形的高度设置为0;



在再次单击正方形之前,请检查 toggle

code>函数。看看JavaScript,我期望红色方块的高度被重置为其原始值,而不触发一个过渡。转移应该被抑制,因为当高度改变时,transition属性暂时设置为 none



再次点击广场。两个彩色方块立即变为完全不透明,但红色方块向下滑动,因为其高度从0转变为原始值。在元素可见之前,通过 toggle 函数不会删除由内联样式设置的高度,因此transition属性也被重置。 p>

触发回流似乎强制应用高度变化。 (取消注释包含 offsetParent 的行来测试。)这种行为发生在浏览器(至少是Chrome和Safari,Firefox和Opera),所以我想知道, t部分规格。我已检查 CSS转换模块,但未成功。

解决方案

这真的是一个奇怪的问题。我不认为你在你的代码中做错了 - 当前的浏览器实现只是bug。



我遇到了这些看起来很明显的错误之前的CSS转换,并且他们是一个巨大的痛苦处理,而不诉诸拜占庭式黑客,一旦他们正在解决的错误,这是肯定会打破固定(在这种情况下,我的WebKit修复)。



我真的深入这个,但不能想出一个干净的解决方案,在三个主要转换支持布局引擎(WebKit,Gecko和Presto)。也就是说,这里是我做的 - 希望有人比我聪明(或只是用新鲜的眼睛来看)可以采取这个答案,并把它变成真正的解决方案。



Gecko和Presto(但不是WebKit!)



看起来像(我不是浏览器工程师或熟悉规范)将继续呈现 transition-property 的任何当前值或先前值,而不管是否需要。因此,即使您已更改 transition-property 的值,浏览器仍然在后台渲染高度过渡,当您更改高度时,您将获得



有一个解决方案:在JavaScript中创建转换删除它(之后,没有转换规则应用于 #upper DOM),更改高度,然后重新添加它。不完美,但不是一个错误依赖的黑客。



http://jsfiddle.net/grantheaslip/e3quW/



JavaScript



  upper.style.removeProperty('transition'); 
upper.style.removeProperty(' - o-transition');
upper.style.removeProperty(' - moz-transition');
upper.style.removeProperty(' - webkit-transition');
upper.style.removeProperty('height');
//强制回流
// if(upper.offsetParent){/ * empty * /}
upper.style ['transition'] ='height 1000ms';
upper.style [' - o-transition'] ='height 1000ms';
upper.style [' - moz-transition'] ='height 1000ms';
upper.style [' - webkit-transition'] ='height 1000ms';



样式表



 code> #upper {
background-color:red;
}



WebKit(但不是Gecko或Presto!)



任何只因为1ms超时才起作用的东西,可能永远不会在生产之外的任何地方,但我认为这是值得指出的,如果它帮助有人找到这个问题的底部。



我的猜测是WebKit没有与Presto或Gecko相同的问题,而是包括一个优化,收集在同一个函数中应用的样式更改,并一次性应用它们。再次,从没有靠近WebKit源或CSS3规范的人的纯粹猜测。



http://jsfiddle.net/grantheaslip/DFcg9/



JavaScript



  window.setTimeout(function(){
upper.style.removeProperty('transition-property');
upper.style.removeProperty -transition-property');
upper.style.removeProperty(' - moz-transition-property');
upper.style.removeProperty(' - webkit-transition-property');
upper.style.removeProperty('opacity');
lower.style.removeProperty('opacity');
},1);



Gecko,Presto和WebKit



这两个解决方案组合。再次,由于超时黑客,这真的不应该使用。



http://jsfiddle.net/grantheaslip/N3NrB/


A live example can be seen here.

A red square (showing) is directly above a green square (hidden as overflow). Click on the square, and both colored squares are instantly made fully transparent. Additionally, the height of the red square is set to 0; this fires a transition, but the transition goes unseen because the red square is now transparent.

Before clicking the square again, examine the toggle function. Looking at the JavaScript, I would expect the height of the red square to be reset to its original value without firing a transition. The transition should be suppressed, because the transition property is temporarily set to none while the height is changed.

Now click on the square again. Both colored squares are instantly made fully opaque, but the red square slides down as its height transitions from 0 to the original value. It's as though the height set by the inline style wasn't removed by the toggle function until the element was visible, and by then the transition property had also been reset.

Triggering a reflow seems to force the change in height to be applied. (Uncomment the line containing offsetParent to test.) This behavior occurs across browsers (at least Chrome and Safari, Firefox, and Opera), so I'm wondering if it isn't part of some spec. I've checked the CSS Transitions Module without success. Any ideas why this behavior occurs, and why it's so consistent across implementations?

解决方案

This really is a bizarre problem. I don't think you're doing anything wrong in your code—the current browser implementations are just buggy.

I've run into these kind of seemingly-obvious bugs before with CSS transitions, and they're a huge pain to deal with without resorting to byzantine hacks that are sure to break once the bug they're working around is fixed (in this case, my WebKit fix).

I really dug into this, but couldn't come up with a clean solution that worked in the three main transitions-supporting layout engines (WebKit, Gecko, and Presto). That said, here's what I did figure out—hopefully someone smarter than me (or just coming at this with fresh eyes) can take this answer and turn it into true solution.

Gecko and Presto (but not WebKit!)

It looks like (and I am not a browser engineer or familiar with the spec) that any current or previous value of a transition-property will continue to be rendered regardless of whether or not it needs to be. So even though you've changed the value of transition-property, the browser is still rendering the height transition in the background, and when you change the height back, you get the trailing end of that.

There is a solution though: create the transition in JavaScript (don't put it anywhere in the style sheet), remove it (after which there are no transition rules applied to #upper anywhere in the DOM), change the height, and then re-add it. Not perfect, but not a bug-reliant hack either.

http://jsfiddle.net/grantheaslip/e3quW/

JavaScript

upper.style.removeProperty('transition');
upper.style.removeProperty('-o-transition');
upper.style.removeProperty('-moz-transition');
upper.style.removeProperty('-webkit-transition');
upper.style.removeProperty('height');
// force a reflow
// if (upper.offsetParent) { /* empty */ }
upper.style['transition'] = 'height 1000ms';
upper.style['-o-transition'] = 'height 1000ms';
upper.style['-moz-transition'] = 'height 1000ms';
upper.style['-webkit-transition'] = 'height 1000ms';

Style sheet

#upper {
    background-color: red;
}

WebKit (but not Gecko or Presto!)

Anything that only works because of a 1ms timeout probably should never go anywhere near production, but I think this is worth pointing out in case it helps someone get to the bottom of this problem.

My guess is that WebKit doesn't have the same issue as Presto or Gecko, but instead includes an optimization that gathers style changes applied in the same function and applies them all at once. Again, pure speculation from someone who's never gone near the WebKit source or CSS3 spec.

http://jsfiddle.net/grantheaslip/DFcg9/

JavaScript

window.setTimeout(function() {
    upper.style.removeProperty('transition-property');
    upper.style.removeProperty('-o-transition-property');
    upper.style.removeProperty('-moz-transition-property');
    upper.style.removeProperty('-webkit-transition-property');
    upper.style.removeProperty('opacity');
    lower.style.removeProperty('opacity');
}, 1);

Gecko, Presto, and WebKit

Here's both solutions combined. Again, because of the timeout hack, this really shouldn't be used.

http://jsfiddle.net/grantheaslip/N3NrB/

这篇关于为什么在设置属性后显示元素时隐藏元素时发生转移?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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