在JavaScript中计算元素宽度会产生错误的结果

Amm*_*sfi 6 javascript css

div文档中有一些简单的样式.它width不是在HTML中设置的,也不是在CSS中设置的.我尝试使用不同的方法在JavaScript中计算其实际宽度:

  • offsetWidth
  • clientWidth
  • getBoundingClientRect().width
  • getComputedStyle(element).getPropertyValue('width')

但是他们都没有返回Chrome Developer Tools中可以看到的实际宽度.

这是一个演示此问题的代码:

var resumeHeader = document.querySelector('#resume-header');
var resumeHeaderComputedWidth = getComputedStyle(resumeHeader, null).getPropertyValue('width');
console.log(resumeHeaderComputedWidth)
console.log(resumeHeader.offsetWidth);
console.log(resumeHeader.clientWidth)
console.log(resumeHeader.getBoundingClientRect().width)
Run Code Online (Sandbox Code Playgroud)
#resume-header {
        display: inline-block;
        background-color: #F5D061;
        padding: 2px 6px;
        font-weight: bold;
        font-size: 14px;
        position: relative;
        top: 25px;
        left: 0;
        transition: width 1s ease;
        font-family: "Merriweather", serif;
        line-height: 1.8;
        letter-spacing: 1px;
        box-sizing: border-box;
}
Run Code Online (Sandbox Code Playgroud)
<link href="https://fonts.googleapis.com/css?family=Merriweather:300,400" rel="stylesheet">
<div id="resume-header">
    Resume
</div>
Run Code Online (Sandbox Code Playgroud)

请注意,在上面的代码段中,计算的宽度有时是正确的,有时是错误的,而在Chrome中,它总是错误的.

Amm*_*sfi 8

问题

似乎有时计算宽度的JavaScript代码在网页准备好并计算布局之前执行; 我认为不在widthCSS文件中设置属性会导致此问题.

因此,解决方案是将JavaScript代码包装在window侦听"load"事件的事件侦听器中:

addEventListener("load", function () {
    var resumeHeader = document.querySelector('#resume-header');
    var resumeHeaderComputedWidth = getComputedStyle(resumeHeader, null).getPropertyValue('width');
    console.log(resumeHeaderComputedWidth)
}
Run Code Online (Sandbox Code Playgroud)

Safari案例

但是,由于其加载和显示网页的方式,这对Safari不起作用.要解决此问题,请在上述事件侦听器之前添加以下代码行:

window.scrollBy(0,1);
Run Code Online (Sandbox Code Playgroud)

有关Safari的这种行为及其解决方法的更多信息:这里.

工作守则

以下是具有上述修复的代码:

window.scrollBy(0,1);
addEventListener("load", function () {
    var resumeHeader = document.querySelector('#resume-header');
    var resumeHeaderComputedWidth = getComputedStyle(resumeHeader, null).getPropertyValue('width');
    console.log(resumeHeaderComputedWidth);
    console.log(resumeHeader.offsetWidth);
    console.log(resumeHeader.clientWidth);
    console.log(resumeHeader.getBoundingClientRect().width);
});
Run Code Online (Sandbox Code Playgroud)
#resume-header {
        display: inline-block;
        background-color: #F5D061;
        padding: 2px 6px;
        font-weight: bold;
        font-size: 14px;
        position: relative;
        top: 25px;
        left: 0;
        transition: width 1s ease;
        font-family: "Merriweather", serif;
        line-height: 1.8;
        letter-spacing: 1px;
        box-sizing: border-box;
}
Run Code Online (Sandbox Code Playgroud)
<link href="https://fonts.googleapis.com/css?family=Merriweather:300,400" rel="stylesheet">
<div id="resume-header">
    Resume
</div>
Run Code Online (Sandbox Code Playgroud)

注意:此解决方案已在Chrome,Safari和Chrome移动版上试用过.