立即读取元素'CSS更改后的视觉属性

Immediately read an element's visual properties after a CSS change?

本文关键字:属性 视觉 CSS 读取 元素      更新时间:2023-09-26

我正在尝试使用CSS更改HTML页面上的一个元素,然后立即读取其视觉属性。然而,CSS强制样式要到稍后(下一个"帧")才能应用。

CSS:

.node {
    width: 10px;
}

JavaScript:

// Create element
var element = document.createElement("div");
element.className = "node";
document.body.appendChild(element);
console.log(element.clientWidth);

上面的log调用的输出应该是10,但如果立即调用它,它就是NaN(但在一帧之后它被正确地读取为10)。

使用getComputedStyle()可以得到类似的结果:

var style = getComputedStyle(element);
console.log(element.style);

第一次运行时输出为",但在第一帧之后输出为"10px"(正确)。

我假设我必须等待一次浏览器的重新布局,直到我可以读取属性。有没有办法强制浏览器计算该元素的尺寸?或者这可能是一种糟糕的做法;有没有一种简单的方法可以读取CSS的width属性?

换句话说,这里的最佳做法是什么?

注意:尽量避免在这里使用jQuery或其他库。

请尝试访问computedStyle

var computedStyle = document.defaultView ? document.defaultView.getComputedStyle(element, null) : element.currentStyle;

然后读取

console.log( computedStyle.width);

示例:http://jsfiddle.net/mGCT5/1/

您说得对,浏览器必须执行回流,然后才能确定更改后的属性的效果(从而读取更改后的值)。我相信你知道,JavaScript是由浏览器的内部事件循环执行的。直到当前事件的JS代码被完全执行后才会执行回流。

为了解决您的问题,您可以使用setImmediate()。这允许您对要尽快处理的新事件进行排队。你基本上是"屈服"的,允许回流发生,然后跳回来完成代码的其余部分:

var element = document.createElement("div");
element.className = "node";
document.appendChild(element);
setImmediate(function() {
    console.log(element.clientWidth);
});

请注意,到目前为止,很少有流行的浏览器支持setImmediate。作为一种变通方法,您可以使用延迟为0:的setTimeout

setTimeout(function() {
    console.log(element.clientWidth);
}, 0);

下面是一个工作示例:jsbin.com/ehigor

还要记住,放在setTimeout块之后的任何代码都将在块内部的代码之前执行,在当前"帧"结束之前执行,因此在回流之前执行。

更新:

jAndy的回答是对的;getComputedStyle将解决OP的问题。在这种情况下,不需要回流,因为您所要做的只是按照设置读取CSS属性。

之所以需要getComputedStyle,是因为JavaScript中没有设置样式规则。与element.style不同,getComputedStyle将考虑外部CSS文件中设置的样式规则以及浏览器的默认样式规则。

在某些情况下,getComputedStyle不够,需要回流:当样式规则的值与样式的实际最终值不直接相关时。最显著的情况是相对维度和位置。如果将width设置为(例如)50%,但要读取元素的宽度(以像素为单位),则只能通过让浏览器执行回流来找出该值(在这种情况下setTimeout很有用)。另一方面,如果您想知道width被设置为"50%";使用CCD_ 22。

在检查宽度之前,可以使用setTimeout等待半秒钟?