最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

css - Calculating element width in JavaScript gives wrong results - Stack Overflow

programmeradmin3浏览0评论

There is a simple div in the document with some styles. Its width is not set in HTML nor in CSS. I tried to calculate its actual width in JavaScript using different methods:

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

but none of them returned the actual width which can be seen in Chrome Developer Tools.

Here is a code that demonstrate this issue:

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)
#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;
}
<link href=":300,400" rel="stylesheet">
<div id="resume-header">
    Resume
</div>

There is a simple div in the document with some styles. Its width is not set in HTML nor in CSS. I tried to calculate its actual width in JavaScript using different methods:

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

but none of them returned the actual width which can be seen in Chrome Developer Tools.

Here is a code that demonstrate this issue:

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)
#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;
}
<link href="https://fonts.googleapis./css?family=Merriweather:300,400" rel="stylesheet">
<div id="resume-header">
    Resume
</div>

Please note that in the above snippet, the calculated width is sometimes correct and sometimes wrong, while in Chrome, it is always wrong.

Share Improve this question asked Oct 16, 2017 at 14:35 Ammar AlyousfiAmmar Alyousfi 4,3825 gold badges32 silver badges46 bronze badges 7
  • 2 Have you tried innerWidth and outerWidth? :) – FluffyKitten Commented Oct 16, 2017 at 14:37
  • Aren't they window properties? How can I use them in this case? – Ammar Alyousfi Commented Oct 16, 2017 at 14:44
  • They are also jQuery functions that can be used on any element to get the height with/without margin, border etc. Ref: innerWidth and outerWidth – FluffyKitten Commented Oct 16, 2017 at 14:49
  • I am using plain JavaScript on my web page. I don't want to add jQuery overhead, especially that the problem can be solved without that :) – Ammar Alyousfi Commented Oct 16, 2017 at 14:52
  • 1 It was just a suggestion, which is why I only added it as a ment rather than an answer. But you had listed every other width, so I thought you might like to go for the full set :) – FluffyKitten Commented Oct 16, 2017 at 14:55
 |  Show 2 more ments

1 Answer 1

Reset to default 13

The Problem

It seems that sometimes the JavaScript code that calculates the width is executed before the web page is ready and the layout is calculated; I think that not setting the width property in the CSS file causes this issue.

Solution

So the solution is to wrap the JavaScript code in an event listener on window that listens for "load" event:

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

Safari Case

However, this doesn't work with Safari due to its way of loading and displaying web pages. To work around this, add this line of code before the event listener described above:

window.scrollBy(0,1);

More info on this behavior of Safari and its workaround: Here.

Working Code

Here is the code with the above fixes:

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);
});
#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;
}
<link href="https://fonts.googleapis./css?family=Merriweather:300,400" rel="stylesheet">
<div id="resume-header">
    Resume
</div>

Note: This solution has been tried on Chrome, Safari, and Chrome for mobile.

发布评论

评论列表(0)

  1. 暂无评论