1164

Suppose that I have a <div> that I wish to center in the browser's display (viewport). To do so, I need to calculate the width and height of the <div> element.

What should I use? Please include information on browser compatibility.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
snortasprocket
  • 11,801
  • 3
  • 19
  • 8
  • 18
    Keep in mind that getting an element's height through **any method** always has a **performance impact** as it makes the browser recalculate the position of all elements in the page (reflow). Therefore, avoid doing it too much. Checkout [this list](https://gist.github.com/paulirish/5d52fb081b3570c81e3a) for what kind of things trigger a reflow. – Marcelo Lazaroni Dec 05 '16 at 03:16

17 Answers17

1651

You should use the .offsetWidth and .offsetHeight properties. Note they belong to the element, not .style.

var width = document.getElementById('foo').offsetWidth;

The .getBoundingClientRect() function returns the dimensions and location of the element as floating-point numbers after performing CSS transforms.

> console.log(document.getElementById('foo').getBoundingClientRect())
DOMRect {
    bottom: 177,
    height: 54.7,
    left: 278.5,​
    right: 909.5,
    top: 122.3,
    width: 631,
    x: 278.5,
    y: 122.3,
}
Alan W. Smith
  • 24,647
  • 4
  • 70
  • 96
Greg
  • 316,276
  • 54
  • 369
  • 333
  • 211
    Beware! offsetHeight/offsetWidth can return 0 if you've done certain DOM modifications to the element recently. You may have to call this code in a setTimeout call after you've modified the element. – Dan Fabulich Jan 19 '10 at 05:59
  • 34
    Under what circumstances does it return 0? – Cheetah Feb 22 '12 at 23:22
  • 7
    I can't pinpoint the reason that `offsetWidth` is returning 0 in my case, because I didn't originally write the code, but within the `onload` event I get always 0. – JDandChips Nov 02 '12 at 08:52
  • 57
    @JDandChips: `offsetWidth` will be 0 if the element is `display:none`, whereas the computed `width` might still have a positive value in this instance. `visibility:hidden` does not affect the `offsetWidth`. – MrWhite Nov 16 '12 at 00:16
  • is `clientWidth` more accurate? – Ky - Nov 10 '14 at 18:42
  • 29
    @Supuhstar both have different meanings. `offsetWidth` returns the "whole" box including content, padding, and borders; while `clientWidth` returns the size of the content box alone (so it will have a smaller value whenever the element has any non-zero padding and/or border). *(mod edited for clarity)* – Edurne Pascual Dec 01 '14 at 14:41
  • 2
    @Supuhstar, they will be the same sometimes, such as when you set `box-sizing: border-box`, which is done with Bootstrap (and I'm sure others) automatically. – trysis May 04 '15 at 21:28
  • Note: in the case of an icon within a button, chrome and firefox return different results: https://github.com/lingtalfi/browsers-behaviours/blob/master/get-bounding-client-rect/bcr-icon.md – ling Oct 09 '16 at 07:03
  • Re @DanFabulich: Using requestAnimationFrame over setTimeout is (probably) preferable in 2017. – Graham P Heath Jun 15 '17 at 18:08
  • 1
    According to https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight Support for Chrome and Safari for `offsetHeight` is unknown(?), and it says it's an "experimental feature" - can this be counted as cross-browser? This comment was written on **March 2019**! – Yuval A. Feb 28 '19 at 23:03
  • Both offset and client width display 0, despite having text in the div, and after a mouse click. – Edward Nov 16 '19 at 18:52
  • can anyone give an example where `offsetHeight` returns `0`? I tried to create one but could not reproduce. https://codepen.io/tranvansang/pen/wvgxRPL – Sang Apr 18 '21 at 03:31
  • The `offsetWidth` always seems to be rounded, e.g. it reports `221` when the inspector says it is `220.78`. This makes a difference when adding up adjacent widths. Is there some way to get the real value? – user9645 Dec 21 '22 at 13:06
262

Take a look at Element.getBoundingClientRect().

This method will return an object containing the width, height, and some other useful values:

{
    width: 960,
    height: 71,
    top: 603,
    bottom: 674,
    left: 360,
    right: 1320
}

For Example:

var element = document.getElementById('foo');
var positionInfo = element.getBoundingClientRect();
var height = positionInfo.height;
var width = positionInfo.width;

I believe this does not have the issues that .offsetWidth and .offsetHeight do where they sometimes return 0 (as discussed in the comments here)

Another difference is getBoundingClientRect() may return fractional pixels, where .offsetWidth and .offsetHeight will round to the nearest integer.

IE8 Note: getBoundingClientRect does not return height and width on IE8 and below.*

If you must support IE8, use .offsetWidth and .offsetHeight:

var height = element.offsetHeight;
var width = element.offsetWidth;

Its worth noting that the Object returned by this method is not really a normal object. Its properties are not enumerable (so, for example, Object.keys doesn't work out-of-the-box.)

More info on this here: How best to convert a ClientRect / DomRect into a plain Object

Reference:

Zach Lysobey
  • 14,959
  • 20
  • 95
  • 149
  • 17
    getboundingClientRect() will return the actual width and height of elements scaled via css whereas `offsetHeight` and `offsetWidth` will not. – Luke Mar 05 '16 at 01:16
  • @Luke not just that it will return floating point number which is a necesessity if you ever need to work with precise calculations, like cropper implementations. – ado387 Aug 22 '23 at 11:41
78

NOTE: this answer was written in 2008. At the time the best cross-browser solution for most people really was to use jQuery. I'm leaving the answer here for posterity and, if you're using jQuery, this is a good way to do it. If you're using some other framework or pure JavaScript the accepted answer is probably the way to go.

As of jQuery 1.2.6 you can use one of the core CSS functions, height and width (or outerHeight and outerWidth, as appropriate).

var height = $("#myDiv").height();
var width = $("#myDiv").width();

var docHeight = $(document).height();
var docWidth = $(document).width();
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
62

Just in case it is useful to anyone, I put a textbox, button and div all with the same css:

width:200px;
height:20px;
border:solid 1px #000;
padding:2px;

<input id="t" type="text" />
<input id="b" type="button" />
<div   id="d"></div>

I tried it in chrome, firefox and ie-edge, I tried with jquery and without, and I tried it with and without box-sizing:border-box. Always with <!DOCTYPE html>

The results:

                                                               Firefox       Chrome        IE-Edge    
                                                              with   w/o    with   w/o    with   w/o     box-sizing

$("#t").width()                                               194    200    194    200    194    200
$("#b").width()                                               194    194    194    194    194    194
$("#d").width()                                               194    200    194    200    194    200

$("#t").outerWidth()                                          200    206    200    206    200    206
$("#b").outerWidth()                                          200    200    200    200    200    200
$("#d").outerWidth()                                          200    206    200    206    200    206

$("#t").innerWidth()                                          198    204    198    204    198    204
$("#b").innerWidth()                                          198    198    198    198    198    198
$("#d").innerWidth()                                          198    204    198    204    198    204

$("#t").css('width')                                          200px  200px  200px  200px  200px  200px
$("#b").css('width')                                          200px  200px  200px  200px  200px  200px
$("#d").css('width')                                          200px  200px  200px  200px  200px  200px

$("#t").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#b").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#d").css('border-left-width')                              1px    1px    1px    1px    1px    1px

$("#t").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#b").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#d").css('padding-left')                                   2px    2px    2px    2px    2px    2px

document.getElementById("t").getBoundingClientRect().width    200    206    200    206    200    206
document.getElementById("b").getBoundingClientRect().width    200    200    200    200    200    200
document.getElementById("d").getBoundingClientRect().width    200    206    200    206    200    206

document.getElementById("t").offsetWidth                      200    206    200    206    200    206
document.getElementById("b").offsetWidth                      200    200    200    200    200    200
document.getElementById("d").offsetWidth                      200    206    200    206    200    206
Graham
  • 7,807
  • 20
  • 69
  • 114
  • 2
    Just to be clear... do any of those browsers do anything differently from eachother? I cannot find any differences... Also, I'm not down-voting (yet), but this doesn't *really* directly answer the question, though it could be easily editted to do so. – Zach Lysobey Mar 11 '16 at 19:35
  • 4
    Wasn't aimed at answering the question - its already been answered. Just some helpful information and yes all the main latest version browsers do agree on these values - which is a good thing. – Graham Mar 14 '16 at 11:13
  • 5
    Well... if your intent is *not* to answer the question, then this doesn't really belong here (as an "answer"). I would consider putting this in some external resource (maybe a GitHub gist, or a blog post) and linking it in a comment on the original Question or one of the answers. – Zach Lysobey Mar 14 '16 at 19:50
  • 25
    @ZachLysobey There's exceptions to every rule - and this is a cool, useful thing to see. – Dan Nissenbaum Sep 12 '16 at 09:28
33

According to MDN: Determining the dimensions of elements

offsetWidth and offsetHeight return the "total amount of space an element occupies, including the width of the visible content, scrollbars (if any), padding, and border"

clientWidth and clientHeight return "how much space the actual displayed content takes up, including padding but not including the border, margins, or scrollbars"

scrollWidth and scrollHeight return the "actual size of the content, regardless of how much of it is currently visible"

So it depends on whether the measured content is expected to be out of the current viewable area.

HarlemSquirrel
  • 8,966
  • 5
  • 34
  • 34
  • 2
    thanks: here is an article about that https://www.javascripttutorial.net/javascript-dom/javascript-width-height/ – CrandellWS Aug 28 '20 at 23:38
8

It is easy to modify the elements styles but kinda tricky to read the value.

JavaScript can't read any element style property (elem.style) coming from css(internal/external) unless you use the built in method call getComputedStyle in javascript.

getComputedStyle(element[, pseudo])

Element: The element to read the value for.
pseudo: A pseudo-element if required, for instance ::before. An empty string or no argument means the element itself.

The result is an object with style properties, like elem.style, but now with respect to all css classes.

For instance, here style doesn’t see the margin:

<head>
  <style> body { color: red; margin: 5px } </style>
</head>
<body>

  <script>
    let computedStyle = getComputedStyle(document.body);

    // now we can read the margin and the color from it

    alert( computedStyle.marginTop ); // 5px
    alert( computedStyle.color ); // rgb(255, 0, 0)
  </script>

</body>

So modified your javaScript code to include the getComputedStyle of the element you wish to get it's width/height or other attribute

window.onload = function() {

    var test = document.getElementById("test");
    test.addEventListener("click", select);


    function select(e) {                                  
        var elementID = e.target.id;
        var element = document.getElementById(elementID);
        let computedStyle = getComputedStyle(element);
        var width = computedStyle.width;
        console.log(element);
        console.log(width);
    }

}

Computed and resolved values

There are two concepts in CSS:

A computed style value is the value after all CSS rules and CSS inheritance is applied, as the result of the CSS cascade. It can look like height:1em or font-size:125%.

A resolved style value is the one finally applied to the element. Values like 1em or 125% are relative. The browser takes the computed value and makes all units fixed and absolute, for instance: height:20px or font-size:16px. For geometry properties resolved values may have a floating point, like width:50.5px.

A long time ago getComputedStyle was created to get computed values, but it turned out that resolved values are much more convenient, and the standard changed.
So nowadays getComputedStyle actually returns the resolved value of the property.

Please Note:

getComputedStyle requires the full property name

You should always ask for the exact property that you want, like paddingLeft or height or width. Otherwise the correct result is not guaranteed.

For instance, if there are properties paddingLeft/paddingTop, then what should we get for getComputedStyle(elem).padding? Nothing, or maybe a “generated” value from known paddings? There’s no standard rule here.

There are other inconsistencies. As an example, some browsers (Chrome) show 10px in the document below, and some of them (Firefox) – do not:

<style>
  body {
    margin: 30px;
    height: 900px;
  }
</style>
<script>
  let style = getComputedStyle(document.body);
  alert(style.margin); // empty string in Firefox
</script>

for more information https://javascript.info/styles-and-classes

Lekens
  • 1,823
  • 17
  • 31
6

You only need to calculate it for IE7 and older (and only if your content doesn't have fixed size). I suggest using HTML conditional comments to limit hack to old IEs that don't support CSS2. For all other browsers use this:

<style type="text/css">
    html,body {display:table; height:100%;width:100%;margin:0;padding:0;}
    body {display:table-cell; vertical-align:middle;}
    div {display:table; margin:0 auto; background:red;}
</style>
<body><div>test<br>test</div></body>

This is the perfect solution. It centers <div> of any size, and shrink-wraps it to size of its content.

Kornel
  • 97,764
  • 37
  • 219
  • 309
4

This is the only thing that worked for me:

element.clientWidth -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-left")) -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-right"))
fguillen
  • 36,125
  • 23
  • 149
  • 210
2

element.offsetWidth and element.offsetHeight should do, as suggested in previous post.

However, if you just want to center the content, there is a better way of doing so. Assuming you use xhtml strict DOCTYPE. set the margin:0,auto property and required width in px to the body tag. The content gets center aligned to the page.

questzen
  • 3,260
  • 18
  • 21
  • 1
    I think he wants to center it vertically too, which is a right pain with CSS unless you can meet some specific criteria (e.g. known-size content) – Greg Nov 16 '08 at 19:53
2

also you can use this code:

var divID = document.getElementById("divid");

var h = divID.style.pixelHeight;
Sergio
  • 28,539
  • 11
  • 85
  • 132
1

... seems CSS help to put div on center ...

<style>
 .monitor {
 position:fixed;/* ... absolute possible if on :root */
 top:0;bottom:0;right:0;left:0;
 visibility:hidden;
 }
 .wrapper {
 width:200px;/* this is size range */
 height:100px;
 position:absolute;
 left:50%;top:50%;
 visibility:hidden;
 }

 .content {
 position:absolute;
 width: 100%;height:100%;
 left:-50%;top:-50%;
 visibility:visible;
 }

</style>

 <div class="monitor">
  <div class="wrapper">
   <div class="content">

 ... so you hav div 200px*100px on center ...

  </div>
 </div>
</div>
sanecin
  • 35
  • 3
0

Flex

In case that you want to display in your <div> some kind of popUp message on screen center - then you don't need to read size of <div> but you can use flex

.box {
  width: 50px;
  height: 20px;
  background: red;
}

.container {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  width: 100vw;
  position: fixed; /* remove this in case there is no content under div (and remember to set body margins to 0)*/
}
<div class="container">
  <div class="box">My div</div>
</div>
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
0

I created a utility function for this, with high flexibility:

export type Size = {width: number, height: number};
export enum GetSize_Method {
    /** Includes: content, padding. Excludes: border, margin, scroll-bar (if it has one), "position:absolute" descendants. */
    ClientSize = "ClientSize",
    /** Includes: content, padding, border, margin, scroll-bar (if it has one). Excludes: "position:absolute" descendants. */
    OffsetSize = "OffsetSize",
    /** Includes: content, padding, border, margin, scroll-bar (if it has one), "position:absolute" descendants. Excludes: none. */
    ScrollSize = "ScrollSize",
    /** Same as ScrollSize, except that it's calculated after the element's css transforms are applied. */
    BoundingClientRect = "BoundingClientRect",
    /** Lets you specify the exact list of components you want to include in the size calculation. */
    Custom = "Custom",
}
export type SizeComp = "content" | "padding" | "border" | "margin" | "scrollBar" | "posAbsDescendants";

export function GetSize(el: HTMLElement, method = GetSize_Method.ClientSize, custom_sizeComps?: SizeComp[]) {
    let size: Size;
    if (method == GetSize_Method.ClientSize) {
        size = {width: el.clientWidth, height: el.clientHeight};
    } else if (method == GetSize_Method.OffsetSize) {
        size = {width: el.offsetWidth, height: el.offsetHeight};
    } else if (method == GetSize_Method.ScrollSize) {
        size = {width: el.scrollWidth, height: el.scrollHeight};
    } else if (method == GetSize_Method.BoundingClientRect) {
        const rect = el.getBoundingClientRect();
        size = {width: rect.width, height: rect.height};
    } else if (method == GetSize_Method.Custom) {
        const style = window.getComputedStyle(el, null);
        const styleProp = (name: string)=>parseFloat(style.getPropertyValue(name));

        const padding = {w: styleProp("padding-left") + styleProp("padding-right"), h: styleProp("padding-top") + styleProp("padding-bottom")};
        const base = {w: el.clientWidth - padding.w, h: el.clientHeight - padding.h};
        const border = {w: styleProp("border-left") + styleProp("border-right"), h: styleProp("border-top") + styleProp("border-bottom")};
        const margin = {w: styleProp("margin-left") + styleProp("margin-right"), h: styleProp("margin-top") + styleProp("margin-bottom")};
        const scrollBar = {w: (el.offsetWidth - el.clientWidth) - border.w - margin.w, h: (el.offsetHeight - el.clientHeight) - border.h - margin.h};
        const posAbsDescendants = {w: el.scrollWidth - el.offsetWidth, h: el.scrollHeight - el.offsetHeight};

        const sc = (name: SizeComp, valIfEnabled: number)=>custom_sizeComps.includes(name) ? valIfEnabled : 0;
        size = {
            width: sc("content", base.w) + sc("padding", padding.w) + sc("border", border.w)
                    + sc("margin", margin.w) + sc("scrollBar", scrollBar.w) + sc("posAbsDescendants", posAbsDescendants.w),
            height: sc("content", base.h) + sc("padding", padding.h) + sc("border", border.h)
                    + sc("margin", margin.h) + sc("scrollBar", scrollBar.h) + sc("posAbsDescendants", posAbsDescendants.h),
        };
    }
    return size;
}

Usage:

const el = document.querySelector(".my-element");
console.log("Size:", GetSize(el, "ClientSize"));
console.log("Size:", GetSize(el, "Custom", ["content", "padding", "border"]));
Venryx
  • 15,624
  • 10
  • 70
  • 96
-1
div.clientHeight;
div.clientWidth;
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
fruitloaf
  • 1,628
  • 15
  • 10
  • 4
    This answer is in a desperate need of some explanations... – Tomerikoo Apr 30 '23 at 12:43
  • While possibly correct, a code-only answer helps the person who asked the question, it doesn't do them or future visitors any good. Please consider improving your answer. – Rohit Gupta May 01 '23 at 04:10
-4

If offsetWidth returns 0, you can get element's style width property and search it for a number. "100px" -> 100

/\d*/.exec(MyElement.style.width)

Arko
  • 3
  • 2
-4

Here is the code for WKWebView what determines a height of specific Dom element (doesn't work properly for whole page)

let html = "<body><span id=\"spanEl\" style=\"font-family: '\(taskFont.fontName)'; font-size: \(taskFont.pointSize - 4.0)pt; color: rgb(\(red), \(blue), \(green))\">\(textValue)</span></body>"
webView.navigationDelegate = self
webView.loadHTMLString(taskHTML, baseURL: nil)

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("document.getElementById(\"spanEl\").getBoundingClientRect().height;") { [weak self] (response, error) in
        if let nValue = response as? NSNumber {

        }
    }
}
  • just to be clear, this is iOS `swift` code, right? Not JavaScript. I'm witholding a downvote (b/c this may actually be pretty useful) but please note that this does *not* answer the question, and would likely be more appropriate on another, iOS specific, question. If none already exists, perhaps consider asking one and self-answering. – Zach Lysobey Oct 30 '18 at 21:19
-6

Use width param as follows:

   style={{
      width: "80%",
      paddingLeft: 100,
      paddingRight: 200,
      paddingTop: 30,
      paddingBottom: 30,
      border: "3px solid lightGray",
    }}
user1767599
  • 47
  • 1
  • 6