Understanding offsetWidth, clientWidth, scrollWidth and -Height, respectively
The CSS box model is rather complicated, particularly when it comes to scrolling content. While the browser uses the values from your CSS to draw boxes, determining all the dimensions using JS is not straight-forward if you only have the CSS.
That's why each element has six DOM properties for your convenience: offsetWidth
, offsetHeight
, clientWidth
, clientHeight
, scrollWidth
and scrollHeight
. These are read-only attributes representing the current visual layout, and all of them are integers (thus possibly subject to rounding errors).
Let's go through them in detail:
-
offsetWidth
,offsetHeight
: The size of the visual box incuding all borders. Can be calculated by addingwidth
/height
and paddings and borders, if the element hasdisplay: block
-
clientWidth
,clientHeight
: The visual portion of the box content, not including borders or scroll bars , but includes padding . Can not be calculated directly from CSS, depends on the system's scroll bar size. -
scrollWidth
,scrollHeight
: The size of all of the box's content, including the parts that are currently hidden outside the scrolling area. Can not be calculated directly from CSS, depends on the content.
Try it out: jsFiddle
Since offsetWidth
takes the scroll bar width into account, we can use it to calculate the scroll bar width via the formula
scrollbarWidth = offsetWidth - clientWidth - getComputedStyle().borderLeftWidth - getComputedStyle().borderRightWidth
Unfortunately, we may get rounding errors, since offsetWidth
and clientWidth
are always integers, while the actual sizes may be fractional with zoom levels other than 1.
Note that this
scrollbarWidth = getComputedStyle().width + getComputedStyle().paddingLeft + getComputedStyle().paddingRight - clientWidth
does not work reliably in Chrome, since Chrome returns width
with scrollbar already substracted. (Also, Chrome renders paddingBottom to the bottom of the scroll content, while other browsers don't)
I created a more comprehensive and cleaner version that some people might find useful for remembering which name corresponds to which value. I used Chrome Dev Tool's color code and labels are organized symmetrically to pick up analogies faster:
Note 1:
clientLeft
also includes the width of the vertical scroll bar if the direction of the text is set to right-to-left (since the bar is displayed to the left in that case)Note 2: the outermost line represents the closest positioned parent (an element whose
position
property is set to a value different thanstatic
orinitial
). Thus, if the direct container isn’t a positioned element, then the line doesn’t represent the first container in the hierarchy but another element higher in the hierarchy. If no positioned parent is found, the browser will take thehtml
orbody
element as reference
Hope somebody finds it useful, just my 2 cents ;)
If you want to use scrollWidth to get the "REAL" CONTENT WIDTH/HEIGHT (as content can be BIGGER than the css-defined width/height-Box) the scrollWidth/Height is very UNRELIABLE as some browser seem to "MOVE" the paddingRIGHT & paddingBOTTOM if the content is to big. They then place the paddings at the RIGHT/BOTTOM of the "too broad/high content" (see picture below).
==> Therefore to get the REAL CONTENT WIDTH in some browsers you have to substract BOTH paddings from the scrollwidth and in some browsers you only have to substract the LEFT Padding.
I found a solution for this and wanted to add this as a comment, but was not allowed. So I took the picture and made it a bit clearer in the regard of the "moved paddings" and the "unreliable scrollWidth". In the BLUE AREA you find my solution on how to get the "REAL" CONTENT WIDTH!
Hope this helps to make things even clearer!