In web development, it is inevitable to have to calculate the size and location of the problem, the solution to this problem is to use some of the DOM provided by the API combination of compatibility processing, all the content of about 3 articles to explain. This article, as a first article, introduces DOM properties that DOM provides for size and size, provides some methods of compatibility handling, and combines common scenarios to illustrate how to properly apply these attributes.
1. Correct understanding of offsetwidth, clientwidth, scrollwidth and corresponding height properties
Assuming that the horizontal longitudinal scroll bar of an element is dragged to the end, the corresponding range of properties for Offsetwidth, ClientWidth, ScrollWidth, and so on, is shown in the following illustration:
1 offsetwidth, offsetheight corresponds to the width and height of the box model, which is the same size as we see when using the Chrome review element:
2 scrollwidth, corresponding to the scrollheight is the width and height of the scrolling area, but does not contain the width of the scroll bar! The scrolling area consists of padding and content.
3) Clientwidth,clientheight corresponds to the width and height of the area after the box model has been removed from the border, excluding the width of the scroll bar.
4 Any DOM element, you can quickly get the Offsetwidth,clientwidth,scrollwidh and related height properties through the following APIs:
Dome is a DOM Html element object
Dome.scrollwidth
Dome.scrollheight
Dome.clientwidth
Dome.clientheight
Dome.offsetwidth
Dome.offsetheight
Dome is a DOM Html element object
Dome.scrollwidth
Dome.scrollheight
Dome.clientwidth
Dome.clientheight
Dome.offsetwidth
Dome.offsetheight
5 These properties in modern browsers including PCs and mobile on almost no compatibility issues, you can be assured of use. If you want to know more about the compatibility rules, you can refer to the following 2 articles:
The consortium DOM compatibility–css Object Model View
Cssom view mode Cssom-view-module related collation and introduction
The following is a test of the above related attribute one by one for ordinary HTML elements, HTML root elements and body elements to validate the previous conclusion and summarize some of the experience techniques that can be used directly in the actual coding process. The reason for distinguishing between ordinary HTML elements, HTML root elements, and body elements is that there are some quirks in the HTML root element and the body element that need to be handled with care.
Note:
1, in order to reduce the length of the test posted code is not complete code, but does not affect the learning reference, In addition, the test results given in the paper are in Chrome (version: 45.0) under the operation of the results, in the case of differences in the test result, will also give Ie9,ie10,ie11,firefox (version: 42.0), Opera (version: 34.0) of the test results, no difference will be in the test results, do not test Consider IE8 and below.
2, Safari because the device limit is not tested, in addition it is the same as the chrome kernel, the reliability of the standard support is less than the poor.
3, the old version of the Chrome,firefox,opera also because the limitations of the device can not be tested, but from the browser to the standard support level, these three browsers in the early version of the standards of the standard of the consortium are relatively regular, coupled with these browsers faster replacement, Now the mainstream versions of these browsers are also newer.
4, because does not consider IE8 and below, at the same time the HTML now all uses HTML5, therefore document.compatmode = ' backcompat ' The situation does not consider. However, although the Backcompat mode is IE6 browser, but for Chrome,firefox, there are document.compatmode = ' backcompat ' situation, such as the following page, you use Chrome to open, and print Document.compatmode in the console, you will find that its value is also backcompat (the reason for this page is the html4.0 DTD, if replaced by the html4.01 DTD will not appear in the Chrome and Firefox):
Http://samples.msdn.microsoft.com/workshop/samples/author/dhtml/refs/compatModeCompat.htm
For more information about Compatmode, you can learn from the following resources:
Https://developer.mozilla.org/zh-CN/docs/Web/API/Document/compatMode
https://msdn.microsoft.com/en-us/library/ms533687 (vs.85). aspx
Http://www.cnblogs.com/uedt/archive/2010/09/21/1832402.html
Test the offsetwidth, ClientWidth, scrollwidth, and related height properties of common HTML elements (not body and HTML root elements):
<style type= "Text/css" > HTML, body {margin:0;
} body {padding:100px;
box {overflow:scroll;
width:400px;
height:300px;
padding:20px;
border:10px solid #000;
margin:0 Auto;
Box-sizing:content-box;
}. box-2 {border:1px solid #000; } </style> <body> <div class= "box" > <div class= "box-2" >...</div> </div> </b
ody> <script type= "Text/javascript" > var boxe = Document.queryselectorall ('. box ') [0];
Console.log (' scrollwidth: ' + boxe.scrollwidth);
Console.log (' scrollheight: ' + boxe.scrollheight);
Console.log (' clientwidth: ' + boxe.clientwidth);
Console.log (' clientheight: ' + boxe.clientheight);
Console.log (' offsetwidth: ' + boxe.offsetwidth);
Console.log (' offsetheight: ' + boxe.offsetheight);
</script> <styletype= "Text/css" > HTML, body{margin:0;
} body{padding:100px;
}. box{Overflow:scroll;
width:400px; height:300px;
padding:20px;
border:10px solid #000;
margin:0 Auto;
Box-sizing:content-box;
}. box-2{border:1px solid #000; } </style> <body> <divclass= "box" > <divclass= "box-2" >...</div> </div> </bod
y> <scripttype= "Text/javascript" > var boxe = Document.queryselectorall ('. box ') [0];
Console.log (' scrollwidth: ' + boxe.scrollwidth);
Console.log (' scrollheight: ' + boxe.scrollheight);
Console.log (' clientwidth: ' + boxe.clientwidth);
Console.log (' clientheight: ' + boxe.clientheight);
Console.log (' offsetwidth: ' + boxe.offsetwidth);
Console.log (' offsetheight: ' + boxe.offsetheight); </script>
In this case, the box element has a 400*300, 20px padding and 10px border,chrome corresponding to the case model:
JS Execution Results:
From the box model and JS implementation results are known:
1 offsetwidth and offsetheight with the Chrome review elements see the exact size of the same;
2 clientwidth and clientheight respectively equal to offsetwidth and offsetheight minus the corresponding border (up to a total of 20px, about 20px) and the value of the scroll bar width (chrome under the scroll bar width of 17px);
3 for ScrollWidth because there is no transverse overflow, and because of the overflow:scroll reason, ScrollWidth and clientwidth the same, but did not include the width of the scroll bar, which also validated the previous conclusions;
4 for ScrollHeight, in this example, it actually equals up and down padding (total 40px) + div.box-2 offsetheight (1370px), div.box-2:
5 The above test also has a CSS noteworthy, is box-sizing, the above code box-sizing set to Content-box, if it changed to Border-box, the result is similar, because offsetwidth, ClientWidth and scrollwidth the corresponding area will not change.
6 The results of other browsers are consistent with the 1-5 conclusion.
Test two, verify the HTML root element and the BODY element related offset client scroll width high attribute:
<style type= "Text/css" > HTML, body {margin:0;
Body {border:10px solid #D4D2D2;
box {overflow:scroll;
width:400px;
height:300px;
padding:20px;
border:10px solid #000;
margin:0 Auto;
Box-sizing:content-box;
}. box-2 {border:1px solid #000; } </style> <body> <div class= "box" > <div class= "box-2" >...</div> </div> < div class= "box" > <div class= "box-2" >...</div> </div> <div class= "box" > <div clas s= "Box-2" >...</div> </div> <div class= "box" > <div class= "box-2" >...</div> </
Div> </body> <script> console.log (' doce.scrollwidth: ' + document.documentElement.scrollWidth);
Console.log (' scrollheight: ' + document.documentElement.scrollHeight);
Console.log (' doce.clientwidth: ' + document.documentElement.clientWidth); Console.log (' doce.clientheight: ' + document.documentelement. clientheight);
Console.log (' doce.offsetwidth: ' + document.documentElement.offsetWidth);
Console.log (' doce.offsetheight: ' + document.documentElement.offsetHeight);
Console.log (");
Console.log (' body.scrollwidth: ' + document.body.scrollWidth);
Console.log (' body.scrollheight: ' + document.body.scrollHeight);
Console.log (' body.clientwidth: ' + document.body.clientWidth);
Console.log (' body.clientheight: ' + document.body.clientHeight);
Console.log (' body.offsetwidth: ' + document.body.offsetWidth);
Console.log (' body.offsetheight: ' + document.body.offsetHeight);
</script> <styletype= "Text/css" > HTML, body{margin:0;
body{border:10px solid #D4D2D2;
}. box{Overflow:scroll;
width:400px;
height:300px;
padding:20px;
border:10px solid #000;
margin:0 Auto;
Box-sizing:content-box;
}. box-2{border:1px solid #000; } </style> <body> <divclass= "box" > <divclass= "box-2" >...</div> </div> <divclass= "box" > <divclass= "box-2" >...</div> </div> <divclass= "box" > &L
t;divclass= "Box-2" >...</div> </div> <divclass= "box" > <divclass= "box-2" >...</div>
</div> </body> <script> console.log (' doce.scrollwidth: ' + document.documentElement.scrollWidth);
Console.log (' scrollheight: ' + document.documentElement.scrollHeight);
Console.log (' doce.clientwidth: ' + document.documentElement.clientWidth);
Console.log (' doce.clientheight: ' + document.documentElement.clientHeight);
Console.log (' doce.offsetwidth: ' + document.documentElement.offsetWidth);
Console.log (' doce.offsetheight: ' + document.documentElement.offsetHeight);
Console.log (");
Console.log (' body.scrollwidth: ' + document.body.scrollWidth);
Console.log (' body.scrollheight: ' + document.body.scrollHeight);
Console.log (' body.clientwidth: ' + document.body.clientWidth);
Console.log (' body.clientheight: ' + document.body.clientHeight); ConSole.log (' body.offsetwidth: ' + document.body.offsetWidth);
Console.log (' body.offsetheight: ' + document.body.offsetHeight); </script>
In this example, the body under a total of 4 box elements (total height of 360 * 4 = 1440px), body width is adaptive, body and 10px border, the results of the operation are as follows:
From this result you can see:
1 The BODY element because of the 10px border reason, so clientwidth than offsetwidth less 20px, which is consistent with the theory mentioned earlier, but the magic is the body of the scrollwidth/ ScrollHeight is equal to its offsetwidth/offsetheight,scrollwidth/scrollheight is the width of the element scrolling area, according to the range diagram given above to understand, the body of the scrollwidth/ The scrollheight should be smaller than its offsetwidth/offsetheight;
2 Doce scrollwidth and scrollheight, should be equal to the BODY element offsetwidth and offsetheight, from the operation result, this point is consistent with, But Doce's clientwidth is equal to its offsetwidth, according to the range chart, Doce clientwidth should be equal to offsetwidth minus the width of the scroll bar.
The results of other browsers are also significantly different from Chrome:
IE11:
1 IE11 under the BODY element does not appear under the chrome BODY element problem
2 the HTML root element under IE11 also has a similar problem with chrome
IE10,IE9:
1 ie10,9 under the BODY element does not appear under the chrome BODY element problem
2 ie10,9 HTML root element and no chrome-like problem
Firefox: Consistent with IE11 running results.
Opera: Consistent with the results of the chrome run, it may be because my version of opera uses the same WebKit kernel as chrome.
Looks like IE9 and IE10 is the most normal, it is a bit difficult to understand, online search for a long time, also did not find the relevant data to illustrate these differences, and finally can only take a bold assumption of the way, guess a few can explain the reasons for these problems:
1 First, the Web page overall scrolling, unlike ordinary HTML element scrolling, ordinary HTML element itself is scrolling object, but for Web pages, scrolling object is not necessarily HTML root element or BODY element. Because when the body content is empty, the body height is the height of the 0,html root element is also 0, if this time to HTML or body plus Overflow:scroll CSS, you will see the scroll bar or the right side of the browser window and the bottom, so for the overall web page scrolling, In theory, scrolling objects should be windows, not HTML elements or body elements! But this is not the case, as in the case of a test browser:
For IE10,IE9, its scrolling object is the HTML root element, so the offset of their HTML root element contains the width of the scroll bar;
For other browsers, the scrolling object is window, so the offset of their HTML root element does not contain the width of the scroll bar.
2 second, the normal element occurs when scrolling, the content of the scroll = its contents area + its padding area, when the Web page overall scrolling, scrolling content should be HTML root element! But the reality is not the case, in terms of the test browser:
For Ie9,ie10,ie11,firefox, their scrolling area is the HTML root element, so their documentelement scrollwidth and scrollheight always represent the scrolling area size of the overall Web page!
For Chrome and opera, their scrolling objects are the body elements, so their body scrollwidth and scrollheight always represent the scrolling area of the page as a whole!
3 Third, the browser always documentelement.clientwidth and Documentelement.clientheight described as a Web page visible area to remove the size of the scroll bar, with the content of the Web page does not matter!
These inferences are not unreasonable, take scrolling objects and scrolling area: chrome If you want to use JS scrolling page to a location, without using window.scrollto conditions, you must use Document.body.scrollTop = XXX To deal with, The setting Document.documentElement.scrollTop is invalid, which means that the overall scrolling area of chrome is determined by the rolling area of the body; IE11 and Firefox if you want to use JS scrolling page to a location, without using the window.scrollto conditions, it will Must use Document.documentElement.scrollTop = XXX to handle, the setting Document.body.scrollTop is invalid, explained IE11 and Firefox's whole scrolling area is determined by the HTML root element scrolling area.
2. Using JS to get the size of the DOM object exactly
The common scenarios are:
1 Gets the size of the viewable area of the entire Web page, excluding scroll bars
2 Get the entire page size, including the invisible scrolling area
3 Gets the size of an ordinary HTML element
4 determine whether the element or Web page has a scroll bar
5) Calculate the width of the scroll bar
For these 5 scenario one by one instructions, the following code does not consider IE8 and below, regardless of the HTML4, please also note that viewport settings, to ensure that the visual viewport on the mobile device and layout coincide.
1 How to get the size of the viewable area of the entire Web page, excluding scroll bars
Document.documentElement.clientWidth;
Document.documentElement.clientHeight;
Document.documentElement.clientWidth;
Document.documentElement.clientHeight;
2 How to get the entire page size, including the invisible scrolling area
function PageWidth () {var doc = document.documentelement, BODY = document.body;
if (doc.clientwidth = = window.innerwidth) {return doc["clientwidth"];
Return Math.max (body["ScrollWidth"), doc["ScrollWidth"], body["offsetwidth"], doc["clientwidth"]);
function PageHeight () {var doc = document.documentelement, BODY = document.body;
if (doc.clientheight = = window.innerheight) {return doc["clientheight"];
Return Math.max (body["ScrollHeight"), doc["ScrollHeight"], body["offsetheight"], doc["clientheight"]);
function PageWidth () {var doc = document.documentelement, BODY = document.body;
if (doc.clientwidth = = window.innerwidth) {return doc["clientwidth"];
Return Math.max (body["ScrollWidth"), doc["ScrollWidth"], body["offsetwidth"], doc["clientwidth"]);
function PageHeight () {var doc = document.documentelement, BODY = document.body; if (doc.clientheight = = window.innerheight) {RETurn doc["ClientHeight"];
Return Math.max (body["ScrollHeight"), doc["ScrollHeight"], body["offsetheight"], doc["clientheight"]); }
The window.innerwidth and window.innerheight above are used to get the width of the viewable area of the Web page including the scroll bar, which is also a good compatibility method, but from the actual development situation, we need to not include the scroll bar of the visual area more, so not in front of the separate introduction. In addition, the previous PPK blog also has a compatibility test on these two attributes that can be understood.
3 How to get the size of a normal HTML element
Simple method:
Doce.offsetwidth;
Doce.offsetheight;
Doce.offsetwidth;
Doce.offsetheight;
Using Getboundingclientrect:
var obj = Doce.getboundingclientrect (),
elemwidth,
elemheight;
if (obj) {
if (obj.width) {
elemwidth = obj.width;
Elemheight = obj.height;
} else {
elemwidth = obj.right-obj.left;
Elemheight = Obj.bottom-obj.top;
}
else {
elemwidth = doce.offsetwidth;
Elemheight = doce.offsetheight;
}
var obj = Doce.getboundingclientrect (),
elemwidth,
elemheight;
if (obj) {
if (obj.width) {
elemwidth = obj.width;
Elemheight = obj.height;
} else {
elemwidth = obj.right-obj.left;
Elemheight = Obj.bottom-obj.top;
}
else {
elemwidth = doce.offsetwidth;
Elemheight = doce.offsetheight;
}
Getboundingclientrect will be described in detail in the next article in conjunction with other location-related DOM attributes.
4 determine whether the element or Web page has a scroll bar
function ScrollBarState (elem) {var Doce = document.documentelement, BODY = document.body; if (!elem | | elem = = Document | | elem = = Doce | | elem = = body) {return {ScrollbarX:docE.clientHeight Windo W.innerheight, ScrollbarY:docE.clientWidth Window.innerwidth} if (typeof (Element) = = ' function ' &! ( Elem instanceof (Element) | |
!body.contains (Elem)) {return {scrollbarx:false, scrollbary:false}; var elemstyle = Elem.style, Overflowstyle = {Hidden:elemStyle.overflow = = ' hidden ', hiddenx:elemsty
Le.overflowx = = ' hidden ', HiddenY:elemStyle.overflowY = ' hidden ', Scroll:elemStyle.overflow = ' scroll ',
ScrollX:elemStyle.overflowX = = ' scroll ', ScrollY:elemStyle.overflowY = = ' scroll '}; return {scrollbarX:overflowStyle.scroll | | overflowstyle.scrollx | | (!overflowstyle.hidden &!overflowstyle.hiddenx && elem.clientwidth elem.scrollwidth), scrollbarY:overflowstyle.scroll | | overflowstyle.scrolly | |
(!overflowstyle.hidden &&!overflowstyle.hiddeny && elem.clientheight elem.scrollheight)};
function ScrollBarState (elem) {var Doce = document.documentelement, BODY = document.body; if (!elem | | elem = = Document | | elem = = Doce | | elem = = body) {return {ScrollbarX:docE.clientHeight Windo W.innerheight, ScrollbarY:docE.clientWidth Window.innerwidth} if (typeof (Element) = = ' function ' &! ( Eleminstanceof (Element) | |
!body.contains (Elem)) {return {scrollbarx:false, scrollbary:false}; var elemstyle = Elem.style, Overflowstyle = {Hidden:elemStyle.overflow = = ' hidden ', hiddenx:elemsty
Le.overflowx = = ' hidden ', HiddenY:elemStyle.overflowY = ' hidden ', Scroll:elemStyle.overflow = ' scroll ',
ScrollX:elemStyle.overflowX = = ' scroll ', ScrollY:elemStyle.overflowY = = ' scroll '}; return {scrollbarx: Overflowstyle.scroll | | OVERFLOWSTYLE.SCROLLX | | (!overflowstyle.hidden &!overflowstyle.hiddenx && elem.clientwidth elem.scrollwidth), SCROLLBARY:OVERFL Owstyle.scroll | | overflowstyle.scrolly | |
(!overflowstyle.hidden &&!overflowstyle.hiddeny && elem.clientheight elem.scrollheight)}; }
When the overflow of the x or y direction is scroll, the Scrollbarx of the direction is true, indicating that the scroll bar appears.
5) Calculate the width of the scroll bar
function Scrollbarwidth () {
var Doce = document.documentelement, Body
= document.body,
e = Document.createelement (' div ');
E.style.csstext = ' Position:absolute; Top: -9999px; width:50px; height:50px; Overflow:scroll; ';
Body.appendchild (e);
var _scrollbarwidth = e.offsetwidth-e.clientwidth
body.removechild (e);
return _scrollbarwidth;
}
function Scrollbarwidth () {
var Doce = document.documentelement, Body
= document.body,
e = Document.createelement (' div ');
E.style.csstext = ' Position:absolute; Top: -9999px; width:50px; height:50px; Overflow:scroll; ';
Body.appendchild (e);
var _scrollbarwidth = e.offsetwidth-e.clientwidth
body.removechild (e);
return _scrollbarwidth;
}
This is all in this article and I hope it will help you: In addition, the second part of this article provides the code, based on personal thinking and experience summed up some of the methods, in terms of compatibility may have not been taken into account, if you have encountered other incompatibilities or better code, please do not hesitate to enlighten me, Your guidance is welcome.