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

时间:2012-07-12 14:04:56

标签: javascript html css

我正在尝试使用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)。< / p>

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

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

首次运行时输出为“”,第一帧后输出为“10px”(正确)。

我假设我必须等待一次浏览器的重新布局,直到我可以阅读该属性。有没有办法强制浏览器计算该元素的维度?或许这可能是不好的做法;有没有直接的方法来读取CSS的宽度属性?

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

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

3 个答案:

答案 0 :(得分:2)

尝试改为访问computedStyle

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

然后阅读

console.log( computedStyle.width);

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

答案 1 :(得分:1)

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

要解决您的问题,您可以使用setImmediate()。这允许您对要尽快处理的新事件进行排队。你基本上“屈服”,允许重排发生,然后跳回来完成剩下的代码:

var element = document.createElement("div");
element.className = "node";
document.appendChild(element);

setImmediate(function() {
    console.log(element.clientWidth);
});

请注意,截至目前,很少有流行的浏览器支持setImmediate。要解决此问题,您可以使用setTimeout延迟0

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

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

还要记住,在setTimeout块之后放置的任何代码都将在块内部的代码之前执行,在当前“帧”结束之前执行,因此在重排之前执行。

<强>更新

jAndy's answer是对的; getComputedStyle将解决OP的问题。在这种情况下,不需要重排,因为您要做的就是读取设置的CSS属性。

这需要getComputedStyle的原因是因为未在JavaScript中设置样式规则。与element.style不同,getComputedStyle会考虑外部CSS文件中设置的样式规则以及浏览器的默认样式规则。

有些情况下,getComputedStyle 足够,并且需要重排 :当样式规则的值与实际不直接相关时,风格的最终价值。最值得注意的案例是相对维度和位置。如果您将width设置为(例如)50%,但想要以像素读取元素的宽度,则只能通过让它来查找该值的值浏览器执行重排(在这种情况下setTimeout很有用)。另一方面,如果您想知道width设置为"50%";使用getComputedStyle

答案 2 :(得分:-1)

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