use*_*ca8 14 javascript css performance internet-explorer ie-developer-tools
我一直在使用HTML/SVG javascript驱动的小部件中的IE(包括IE11的所有版本)上的不良性能遇到很多麻烦,只有当小部件托管在某个页面上时.
在确定减速的主要原因是油漆/渲染层重绘之后,并且耗尽了有关这些的信息我可以从IE开发人员工具中解脱出来,我一次尝试关闭一个祖先类的试验和错误,直到性能提高为止; 然后,在识别班级时,一次关闭一个样式规则.
我的整个问题似乎归结为一个overflow: hidden;祖先的单一规则几个divs树.
它的不同之处是令人难以置信:使用overflow: hidden;树,简单的用户交互(突出显示SVG路径,生成HTML文本标签,显示标签并将其相对于SVG路径和容器定位)最大化处理器,减少UI帧速率为零,并且每次交互都会冻结所有死机,持续1,000到4,000毫秒.没有overflow: hidden;祖先,它在数十毫秒内完成,帧速率从不低于一半(非IE浏览器无论如何都是相同的overflow: hidden;).
这里的轮廓用overflow: hidden;的祖先,剖析和越野互动,过滤油漆事件:
这是不在overflow: hidden;祖先上的配置文件,分析开启和关闭交互,过滤以绘制事件.唯一的变化是overflow: hidden;在DOM检查器中样式旁边的勾选框中打勾或取消勾选,并且我执行测试的顺序无关紧要:
我不想仅仅把它overflow: hidden;作为一个粘性石膏覆盖并说完了工作,而不是理解这是如何发生的,并冒着问题再次发生与其他看似微不足道的CSS变化.我更倾向于理解为什么overflow: hidden;会产生这样的差异并以一种强大的方式解决这个问题,无论应用何种溢出规则.
遗憾的是,我无法发布完整的演示,但这里是DOM结构相关部分的摘要,其中包含与布局相关的样式的注释:
<div class="responsive-grid">
<!-- ...lots of nested divs that simply inherit styles, I can't change this aspect of the Drupal layout -->
<div id="panel-5" class="col-12"> <!-- width: 100%; float: left -->
<!-- this is the first element IE looks at for offsetWidth when doing the changes below -->
<!-- ...a few more nested divs without layout-changing styles -->
<div class="panel"> <!-- overflow: hidden; clear: both; border: 1px; -->
<!-- this is the element where removing the overflow: hidden changes everything -->
<!-- I'm not sure what clear:both is for here, since no siblings. Seems redundant -->
<!-- ...a few more nested divs with no style rules, some contain <p>s <h2>s etc... -->
<div class="container"> <!-- position: relative; -->
<div class="sub-column col-8"> <!-- width: 66%; display: inline-block -->
<div class="square"> <!-- width: 100%; padding-bottom: 100%; position: relative -->
<svg viewbox="0 0 500 500" preserveAspectRatio="XMinYMin meet" ...>
<!-- svg position: absolute; width:100%; height: 100% -->
Many paths here
<div class="label"> <!-- fixed width in pixels; position: absolute -->
Some text here
</div>
</div>
</div>
<div class="sub-column col-4"> <!-- width: 33%; display: inline-block -->
<div class="sidebar">
Many interactive controls here
<!-- .square, svg andd .sidebar contain the only elements that are updated -->
</div>
</div>
</div>
<!-- some more ordinary position: static text containers -->
</div>
</div>
</div>
Run Code Online (Sandbox Code Playgroud)
这里可能会发生什么,有没有什么方法可以在不删除/禁止overflow: hidden;祖先元素的情况下阻止它?
我已经看过如何避免溢出的性能成本:隐藏?但问题和答案似乎都是特定于HTML表格和旧的Webkit错误.
它们似乎也特别适用于由溢出物剪切的内容被不必要地绘制的情况; 我的情况的一个怪癖是,overflow: hidden;实际上并没有在这个页面上剪切太多(如果有的话)(但我不能只删除它,因为它是影响数百个其他页面的模板的一部分,它确实有效果).
更新:情节变浓.我已经设法用更简单的HTML结构复制我的小部件的问题,并发现只有在同一容器上设置了两个overflow: hidden;和border-radius(在我的情况下,3px)时才会出现问题.任何一个而不是另一个,问题就消失了.
经过更多的测试后,我想我已经开始明白这里发生了什么.这纯粹是基于观察,所以如果有人的话,我仍然渴望获得更权威的答案.
似乎只有在所有这些都成立的情况下才会发生:
overflow: hidden和border-radius(或-ms-border-radius).在我的测试中,如果同一分支中的不同祖先具有这些样式,则不会发生这种情况.position: absolute;或者position: relative;这个问题似乎与受position: absolute;/ relative和其复杂性影响的元素数量成比例.例如,如果在响应式缩放%宽度SVG容器中存在SVG路径,其中%padding-bottom用于固定宽高比,则问题非常明显; 如果给出了这个分支,position: static但是另一个分支具有带有position: absolute;祖先的%-width div ,那么与去除其中一个overflow: hidden;或者相比,问题仍然是可观察的border-radius,但是严重程度要低得多.
我没有任何确定的答案,但我有一个似乎符合事实的似是而非的理论.具有讽刺意味的是,它是IE的性能优化的一个反击尝试.
我注意到offsetWidthX和路径之间的元素计算一直到路径,这对我没有意义并提示相关的问题,因为SVG容器内的路径肯定不会影响容器外的布局.
我还注意到,在研究这个问题时,其他浏览器 - 特别是旧版本的Chrome - 似乎有一个不同的问题:应该隐藏的元素正在渲染,导致速度减慢.
将这些放在一起,我认为对于这里发生的事情有一个合理的解释.如果是真的,具有讽刺意味的是,我的性能问题是由于IE的反击尝试来优化性能并避免像上面链接的现在修复的Chrome问题那样的问题.
如果这个理论是正确的,IE会发生这样的事情:
overflow: hidden;并得出结论,它可以通过在对它们进行重绘/重排/绘制等事件之前识别完全在元素边界之外的元素来提高性能.position: absolute;并position: relative;进一步向下看,并得出结论认为这些及其子女可能完全在容器之外,可能会被忽视这样border-radius,这仍然会发生,但在这种情况下,它是微不足道的,需要几毫秒.overflow: hidden元素的形状不是矩形,因此需要更复杂的计算来确定哪些是超出范围的如果可以,只需将overflow: hidden或移动border-radius到子元素,使它们不在同一元素上.任务完成.
然而,对我来说,我正在制作一个需要能够被放入任何地方的插件,并且无法控制其部署的页面.我不知道有什么方法可以强迫IE关掉这个行为.
我能想到的最好的方法是假设border-radius样式对于美学并非必不可少,并且overflow: hidden;可能对结构至关重要,因此,如果浏览器是IE,请查找祖先树并border-radius从任何元素中删除它和overflow: hidden;.
我的应用程序已经使用了jQuery,所以这个测试看起来像这样:
if( isAnyIE() ) {
$container.parentsUntil("body").filter(function(){
var $this = $(this),
overflow = $this.css('overflow');
return ( overflow === 'hidden' && hasBorderRadius( $this ) );
}).addClass( 'remove-border-radius' );
}
function hasBorderRadius( $element ){
function getNum( style ){
return parseFloat( $element.css( 'border-'+style+'-radius' ) ) || 0;
}
var number = 0;
number += getNum( 'top-left' );
number += getNum( 'bottom-left' );
number += getNum( 'top-right' );
number += getNum( 'bottom-right' );
$element = null;
return !!number;
}
function isAnyIE(){
// isIE(): use conditional comments and classes, see https://stackoverflow.com/a/18615772/568458
// isIE10: use user agent like navigator.appVersion.indexOf("MSIE 10") !== -1;
// isIE11: use user agent like !!navigator.userAgent.match(/Trident.*rv[ :]*11\./);
return isIE11() || isIE10() || isIE();
}
Run Code Online (Sandbox Code Playgroud)
使用CSS像:
.remove-border-radius {
border-radius: 0 0 0 0 !important;
-ms-border-radius: 0 0 0 0 !important;
}
Run Code Online (Sandbox Code Playgroud)
在Joppe Kroon在2014年2月撰写的这份错误报告中,问题引起了微软的注意:
[IE 9] [IE 11] div的边框半径和溢出 而不是可见的调整大小缓慢填充div的位置 相对
当存在大量具有位置"绝对","固定"或"相对"的组合的大DIV元素,除"可见"以外的溢出和边界半径时,页面的重绘表现非常糟糕.在调整窗口大小或滚动时可以清楚地看到这一点.单个绘画事件最多可能需要1.5秒才能完成,从而导致页面无响应.
此性能问题出现在IE 11和IE 9中,但不出现在IE 10中.
[...]我们仔细研究了您报告的问题,发现它与报告的类似问题非常相似.我们通常的决议("BY DESIGN","DUPLICATE","FIXED"等)都没有完全符合这种情况,因此我们将其标记为"不会修复",因为缺少更好的东西,但我们真正的意思是我们将以一种汇总的方式处理它,而不是在这种确切的情况下查看这个确切的事件.[...]
一切顺利,MS Edge团队
错误的状态是:关闭,因为无法修复
| 归档时间: |
|
| 查看次数: |
1418 次 |
| 最近记录: |