更改 CSS 时强制浏览器触发重排

问题描述 投票:0回答:3

我正在基于 CSS3 过渡构建非 jQuery 响应式图像滑块。

结构很简单:一个视口和内部相对定位的 UL 以及左侧浮动的 LI。

我在这种情况下面临一个问题:

  1. 用户单击“上一个”箭头。
  2. JS 在当前显示的 LI 节点之前附加适当的 LI。
  3. 目前 UL 已将 CSS 过渡设置为
    none 0s linear
    以防止动画更改。此时,我将 UL CSS 左值减小滑块宽度(比方说:从 0px 到 -1200px),以使视图与原来相同。
  4. 现在我将 UL 的过渡属性更改为
    all 0.2s ease-out
  5. 现在我正在更改 UL 的 left 属性以触发 CSS3 动画。 (比方说:从 -1200px 到 0px)。

问题是什么?浏览器简化了更改并且不制作任何动画。

Stoyan Stefanov 在他的博客这里写了有关回流问题的文章,但在这种情况下,尝试在元素上强制回流是行不通的。

这是执行此操作的一段代码(为了简化我跳过了浏览器前缀):

ul.style.transition = 'none 0s linear 0s';
ul.style.left = '-600px';
ul.style.transition = 'all 0.2s ease-out';
ul.style.left = '0px';

这里是查看实际问题的小提琴:http://jsfiddle.net/9WX5b/1/

javascript html css reflow
3个回答
45
投票

请求元素的

offsetHeight
可以很好地完成一切。您可以使用此函数强制回流并向其传递样式已更改的元素:

function reflow(elt){
    console.log(elt.offsetHeight);
}

在需要回流焊的地方调用此方法。请参阅此示例:http://jsfiddle.net/9WX5b/2/

编辑:最近需要这样做,想知道是否有比 console.log 更好的方法。你不能只写

elt.offsetHeight
作为它自己的语句,因为优化器(至少是 Chrome 的)不会触发回流,因为它只是访问一个没有设置 getter 的属性,甚至不需要评估它。所以,据我所知,最便宜的方法是
void(elt.offsetHeight)
,因为它不确定
void
是否有副作用。 (可能会被覆盖或其他什么,idk)。


8
投票
function reflow( element ) {
    if ( element === undefined ) {
        element = document.documentElement;
    }
    void( element.offsetHeight );
}

它可以与 Chrome 和 FF 配合使用,并且似乎是 ATM 上最简单、最便携的方式。


0
投票

requestAnimationFrame
应该适合大多数用例,并且它比依赖 DOM API 的未记录的副作用要干净得多:

el.style.transition = 'none';
requestAnimationFrame(() => {
  el.style.transition = 'all 1s ease';
});
© www.soinside.com 2019 - 2024. All rights reserved.