为什么需要为CSS转换触发重排? [英] Why does reflow need to be triggered for CSS transitions?

查看:177
本文介绍了为什么需要为CSS转换触发重排?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读这篇文章 http://semisignal.com/?p=5298 和作者写道



在删除不可见类之前需要触发回流,以便转换按预期工作。



我的问题是:



1)为什么需要触发回流?



2)我明白我们应该避免使用回流,如果这是真的,为什么作者建议使用回流来使转换工作?



3)使用reflow,是否有不同的方法使转换工作?



谢谢。

解决方案

(实际上:我为什么不能轻易地使用显示属性的转换)



简答



CSS转换依赖于启动 static 元素的属性。当元素设置为 display:none; 时,文档(DOM)将呈现为元素不存在。这意味着当它设置为 display:block; - 没有转换的起始值。



更长的答案


  1. 需要触发回流,因为元素设置为 display:none; 尚未在文档中绘制。这可以防止转换具有起始值/初始状态。将元素设置为 display:none; 使文档呈现,就像元素根本不存在一样。

  2. 他建议回流因为隐藏和显示元素通常被接受 display:none; display:block; - 通常在元素之后已被动作请求(选项卡或按钮单击,回调函数,超时功能等)。转换是UX的巨大奖励,因此回流是允许这些转换发生的相对简单的方法。当您在简单站点上使用简单转换时,它不会产生巨大影响,因此出于一般目的,您可以触发重排,即使技术上您不应该这样做。想想这个人的例子就像在生产站点中使用未经编辑的JavaScript文件一样。 你能吗?当然! 你应该吗?可能不是,但在大多数情况下,它不会产生明显的差异。

  3. 有不同的选项可以阻止回流,或者通常比链接中的方法更容易使用你提供。请参考以下代码段:

A :此元素设置为 height:0; overflow:hidden; 。显示时,它设置为 height:auto; 。我们仅将动画应用于不透明度。这给了我们类似的效果,但我们可以在没有重排的情况下进行转换,因为它已经在文档中呈现并提供了转换初始值。



B :此元素与A相同,但将高度设置为定义的大小。



A和B工作足够为了淡化元素,但因为我们立即将高度从 auto / 100px 设置为 0 ,它们似乎会崩溃关于淡出



C :此元素被隐藏,我们尝试转换孩子。您可以看到这也不起作用,并且需要触发重排。



D :此元素已隐藏且我们动画孩子。由于动画关键帧给出了定义的起始值和结束值,因此效果更好。但请注意,黑匣子会进入视野,因为它仍然附在父母身上。



E :这与D类似,但我们会运行所有内容关闭孩子,这并没有解决我们与D的黑匣子问题。



F :这可能是最好的两个世界的解决方案。我们将父母的样式移到孩子身上。我们可以触发父节点的动画,我们可以控制子节目的 display 属性和 animate 过渡我们想要的。这方面的缺点是你需要使用动画关键帧而不是过渡。



G :虽然我不知道这是否会触发内部的回流我自己没有解析它的函数,你可以简单地使用jQuery的 .fadeToggle()函数来完成所有这一切,只需一行JavaScript,并使用经常(或类似的JS / jQuery fadeIn / fadeOut方法),回流的主题并不常见。



示例:



这是一个CodePen: https://codepen.io/xhynk/pen / gerPKq



这是一个片段:



  jQuery(document).ready(function($){$('button:not(#g)')。click(function(){$(this).next(' DIV)toggleClass(节目); }); $('#g')。click(function(){$(this).next('div')。stop()。fadeToggle(2000);});});  

  * {box-sizing:border-box; }按钮{text-align:center;宽度:400px;} div {margin-top:20px;背景:#000;颜色:#fff;}。a,.b {溢出:隐藏;身高:0;不透明度:0;过渡:不透明度3s;}。a.show {height:auto;不透明度:1;}。b.show {height:100px;不透明度:1;}。c,.d {display:none;}。c.show,.d.show {display:block; } .cc {不透明度:0;过渡:3s all;}。c.show div {opacity:1;}。d div {opacity:0;}。d.show div {animation:fade 3s;} @keyframes fade {from {opacity:0; } {不透明度:1; e div {display:none;}。e.show div {display:block;动画:淡化3s;}。f {background:transparent;}。f div {background:#000; display:none;}。f.show div {display:block;动画:淡出3s;}。g {display:none;}  

 < button id =a> A:Box Height:Auto< / button>< div class =a> This< br /> Has< br /> Some Strange< br /> ;< br />内容< br>但< br>那并不真正< br>事情< br />因为显示,< br />我将< br /> AUTO< / div>< button id =b> B:Box高度:100px< / button>< div class =b> Content For 2< / div>< button id =c> C :Hidden  -  Child Transitions(bad)< / button>< div class =c>< div> Content< br /> For< br /> 3< br />< / div> < / div>< div style =clear:both;>< / div>< button id =d> D:隐藏 - 儿童动画(更好)< / button>< div class =d>< div>内容< br />对于< br /> 4< br />< / div>< / div>< div style =clear:both; >< / div>< button id =e> E:Hidden  -  Child Hidden& Animates< / button>< div class =e>< div>内容< br />用于< br /> 5< br />< / div>< / div><按钮id =f> F:孩子有BG& Animates(Works)< / button>< div class =f>< div> Content< br /> For< br /> 5< br />< / div>< / div> ;< div style =clear:both;>< / div>< button id =g> G:这使用fadeToggle来避免这个< / button>< div class =g> ;我用< br /> JavaScript动画< / div>< footer>我只是显示文档底部的页脚。< / footer>< script src =https://ajax.googleapis的.com / AJAX /库/ jquery的/ 2.1.1 / jquery.min.js>< /脚本>  


I was reading this article http://semisignal.com/?p=5298 and the author wrote that

"Reflow needs to be triggered before the invisible class is removed in order for the transition to work as expected. "

My questions are :

1) Why does reflow need to be triggered?

2) I understand that we should avoid using reflow, if that is true why is the author suggesting to use reflow in order to make the transition work?

3) Instead of using reflow, is there a different method to make the transition work?

Thank you.

解决方案

(Effectively: "Why can't I easily use transitions with the display property")

Short Answer:

CSS Transitions rely on starting or static properties of an element. When an element is set to display: none; the document (DOM) is rendered as though the element doesn't exist. This means when it's set to display: block; - There are no starting values for it to transition.

Longer Answer:

  1. Reflow needs to be triggered because elements set to display: none; are not drawn in the document yet. This prevents transitions from having a starting value/initial state. Setting an element to display: none; makes the document render as if the element isn't there at all.
  2. He suggest reflowing because it's generally accepted to hide and show elements with display: none; and display: block; - typically after the element has been requested by an action (tab or button click, callback function, timeout function, etc.). Transitions are a huge bonus to UX, so reflowing is a relatively simple way to allow these transitions to occur. It doesn't have an enormous impact when you use simple transitions on simple sites, so for general purposes you can trigger a reflow, even if technically you shouldn't. Think of the guy's example like using unminified JavaScript files in a production site. Can you? Sure! Should you? Probably not, but for most cases, it won't make a hugely noticeable difference.
  3. There are different options available that prevent reflowing, or are generally easier to use than the method in the link you provided. Take the following snippet for a few examples:

A: This element is set to height: 0; and overflow: hidden;. When shown, it's set to height: auto;. We apply the animation to only the opacity. This gives us a similar effect, but we can transition it without a reflow because it's already rendered in the document and gives the transitions initial values to work with.

B: This element is the same as A, but sets the height to a defined size.

A and B work well enough for fading in elements, but because we set the height from auto/100px to 0 instantly, they appear to collapse on "fade out"

C: This element is hidden and we attempt to transition the child. You can see that this doesn't work either and requires a reflow to be triggered.

D: This element is hidden and we animate the child. Since the animation keyframes give a defined starting and ending value, this works much better. However note that the black box snaps into view because it's still attached to the parent.

E: This works similarly to D but we run everything off the child, which doesn't solve our "black box" issue we had with D.

F: This is probably the best of both worlds solution. We move the styling off the parent onto the child. We can trigger the animation off of the parent, and we can control the display property of the child and animate the transition as we want. The downside to this being you need use animation keyframes instead of transitions.

G: While I don't know if this triggers a reflow inside the function as I haven't parsed it myself, you can just simply use jQuery's .fadeToggle() function to accomplish all of this with a single line of JavaScript, and is used so often (or similar JS/jQuery fadeIn/fadeOut methods) that the subject of reflowing doesn't come up all that often.

Examples:

Here's a CodePen: https://codepen.io/xhynk/pen/gerPKq

Here's a Snippet:

jQuery(document).ready(function($){
  $('button:not(#g)').click(function(){
  	$(this).next('div').toggleClass('show');
  });

  $('#g').click(function(){
  	$(this).next('div').stop().fadeToggle(2000);
  });
});

* { box-sizing: border-box; }

button {
	text-align: center;
	width: 400px;
}

div {
	margin-top: 20px;
	background: #000;
	color: #fff;
}

.a,
.b {
	overflow: hidden;
	height: 0;
	opacity: 0;
	transition: opacity 3s;
}

.a.show {
	height: auto;
	opacity: 1;
}
.b.show {
	height: 100px;
	opacity: 1;
}

.c,
.d {
	display: none;
}

.c.show,
.d.show {
 display: block;	
}

.c div {
	opacity: 0;
	transition: 3s all;
}

.c.show div {
	opacity: 1;
}

.d div {
	opacity: 0;
}

.d.show div {
	animation: fade 3s;
}

@keyframes fade {
    from { opacity: 0; }
      to { opacity: 1; }
}

.e div {
	display: none;
}

.e.show div {
	display: block;
	animation: fade 3s;
}

.f {
	background: transparent;
}

.f div {
	background: #000;
	display: none;
}

.f.show div {
	display: block;
	animation: fade 3s;
}


.g {
	display: none;
}

<button id="a">A: Box Height: Auto</button>
<div class="a">This<br/>Has<br/>Some Strange<br/><br/>Content<br>But<br>That doesn't really<br>Matter<br/>Because shown,<br/>I'll be<br/>AUTO</div>
<button id="b">B: Box Height: 100px</button>
<div class="b">Content For 2</div>
<button id="c">C: Hidden - Child Transitions (bad)</button>
<div class="c"><div>Content<br/>For<br/>3<br/></div></div>
<div style="clear: both;"></div>
<button id="d">D: Hidden - Child Animates (Better)</button>
<div class="d"><div>Content<br/>For<br/>4<br/></div></div>
<div style="clear: both;"></div>
<button id="e">E: Hidden - Child Hidden & Animates</button>
<div class="e"><div>Content<br/>For<br/>5<br/></div></div>
<button id="f">F: Child Has BG & Animates (Works)</button>
<div class="f"><div>Content<br/>For<br/>5<br/></div></div>
<div style="clear: both;"></div>
<button id="g">G: This uses fadeToggle to avoid this</button>
<div class="g">I animate with<br/>JavaScript</div>
<footer>I'm just the footer to show the bottom of the document.</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

这篇关于为什么需要为CSS转换触发重排?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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