最近在學習JavaScript,特意買了一本犀牛角書來看看,尼瑪一千多頁,看的我頭昏腦漲,翻到DOM這章節,突然記起平常在使用DOM時,碰到了好多的這個dom里面的各種寬度,高度,特意在此寫一寫,寫的不好或者寫錯了,歡迎各位指正。好了廢話不多說,開始進入主題。
這篇文章主要討論兩點:
一、DOM中各種寬度、高度
二、DOM中的坐標系
下面我們看看DOM中都有一些什么寬度、高度。
常見的
| offsetWidth |
clientWidth |
scrollWidth |
| offsetHeight |
clientHeight |
scrollHeight |
| offsetLeft |
clientLeft |
scrollLeft |
| offsetTop |
clientTop |
scrollTop |
下面我們來一一講解
offsetleft:元素的邊框的外邊緣距離與已定位的父容器(offsetparent)的左邊距離(不包括元素的邊框和父容器的邊框)。
offsettop:同理是指元素的邊框的外邊緣距離與已定位的父容器(offsetparent)的上邊距離(不包括元素的邊框和父容器的邊框)。
offsetwidth:描述元素外尺寸寬度,是指 元素內容寬度+內邊距寬度(左右兩個)+邊框(左右兩個),不包括外邊距和滾動條部分。
offsetheight:同理 描述元素外尺寸高度,是指 元素內容高度+內邊距高度(上下兩個)+邊框(上下兩個),不包括外邊距和滾動條部分。
下面我們看一下一段代碼
<div id="divParent" style="padding: 8px; background-color:#CCC; position: relative;">
<div id="divChild" style="background-color:#C00; margin: 30px; padding: 10px;
height: 200px; width: 200px; border: solid 10px #0000CC;">
</div>
</div>
<script type="text/javascript">
var div = document.getElementById('divChild');
var offsetHeight = div.offsetHeight;
var offsetWidth = div.offsetWidth;
div.innerHTML += 'offsetHeight: ' + offsetHeight + '<br />';
div.innerHTML += 'offsetWidth: ' + offsetWidth + '<br />';
var offsetLeft = div.offsetLeft;
var offsetTop = div.offsetTop;
div.innerHTML += 'offsetLeft: ' + offsetLeft + '<br />';
div.innerHTML += 'offsetTop: ' + offsetTop + '<br />';
var offsetParent = div.offsetParent;
div.innerHTML += 'offsetParent: ' + offsetParent.id + '<br />';
</script>
看一下效果

現在我們按照上面的說明比對一下
offsetleft:(div id=divChild)margin 30(外邊距--距離父容器左邊30px)+ (div id=divParent) padding 8 (父容器的內邊左距離 8px)=38
offsettop:margin 30+ padding 8=38;
offsetwidth:本身的寬度(200)+內邊距左右(10*2)+邊框左右(10*2)=240;
offsetheight:同理;
下面我們來看下第二組
clientleft:元素的內邊距的外邊緣和邊框的外邊緣的距離,實際就是邊框的左邊框寬度
clienttop:同理邊框的上邊框的寬度
clientwidth:用於描述元素內尺寸寬度,是指 元素內容+內邊距 大小,不包括邊框、外邊距、滾動條部分
clientheight:同理 用於描述元素內尺寸高度,是指 元素內容+內邊距 大小,不包括邊框、外邊距、滾動條部分
我們只更改一下JavaScript的代碼,DOM不改變
chrome 41 版本

clientleft:左邊框寬度 10;
clienttop:10;
clientwidth:本身寬度(200)+內邊距(10*2)=220;
clientheight:本身高度(200)+內邊距(10*2)=220;
正確,下面我們來看下嵌套的div盒子模型圖
div id=divChild

div id=divParent

符合我們上面所說的,下面我們看下
scrollwidth:內容區域尺寸加上內邊距加上溢出尺寸,當內容正好和內容區域匹配沒有溢出時,這些屬性與clientWidth和clientHeight相等
scrollheight:同上
scrolltop:滾動條上方卷去的高度
scrollleft:滾動條左邊卷去的寬度
好現在我們 看一段代碼
<div id="divParent" style="padding: 8px; background-color: #aaa; height:200px; width:300px; overflow:auto" >
<div id="divChild" style="background-color: #0f0;height: 400px; width: 500px; border: solid 10px #f00;">
</div>
</div>
<script type="text/javascript">
var divParent= document.getElementById("divParent");
var scrollwidth = divParent.scrollWidth;
var scrollheight = divParent.scrollHeight;
var scrolltop = divParent.scrollTop;
var scrollleft = divParent.scrollLeft;
divChild.innerHTML += 'clientWidth: ' + scrollwidth + '<br />';
divChild.innerHTML += 'clientHeight: ' + scrollheight + '<br />';
</script>
現在我們要計算id=divParent的scrollheight,和scrollwidth。根據上面的說明,我們知道應該按照下面的公式計算
scrollwidth=子div的寬度(500)+子div的邊框(10*2)+父容器的padding(8)=528
scrollwidth=子div的高度(400)+子div的邊框(10*2)+父容器的padding(8)=428
現在我們驗證一下
我們發現在 ie8及之后的 瀏覽器 為428,firework 也為428;而 chrome Safari opera 都為436;
因此我們可以猜測 chrome和 Safari、opera 在計算 scrollheight時,加上了 父容器的下 padding(8) 即 428+8=436;
下面我們在看看scrolltop和scrollleft的值怎么樣

測試了好幾個瀏覽器都發現其值為零,這是腫么回事,尼瑪,萬能的百度、谷歌,原來我的滾動條一直在頂端和左端,沒有卷走高度,我們修改一下代碼,將顯示內容綁定到onscroll事件
<script type="text/javascript">
var divParent = document.getElementById("divParent");
divParent.onscroll = function () {
divChild.innerHTML = "";
var scrollwidth = divParent.scrollWidth;
var scrollheight = divParent.scrollHeight;
var scrolltop = divParent.scrollTop;
var scrollleft = divParent.scrollLeft;
divChild.innerHTML += 'clientWidth: ' + scrollwidth + '<br />';
divChild.innerHTML += 'clientHeight: ' + scrollheight + '<br />';
divChild.innerHTML += 'scrolltop: ' + scrolltop + '<br />';
divChild.innerHTML += 'scrollleft: ' + scrollleft + '<br />';
}
</script>
終於發現值改變了
另外我們在使用window的pageXOffset,pageYOffset求瀏覽器滾動條的卷去的高度和左邊的距離,同時scrolltop、scrollleft也可以,但是要注意
當我們網頁頁面申明了dtd(文檔模型時), 使用document.documentElement.scrolltop scrollleft獲取瀏覽器卷去上面的距離,左邊卷去的距離。
如果網頁沒有申明dtd(怪異模式時),使用document.body.scrolltop scrollleft獲取上邊卷去的距離、左邊卷去的距離。
什么是dtd,這里簡單解釋一下,我們使用vs新建頁面時,在每個網頁的頂端 一般會有這樣的申明
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
這里申明了 網頁的模型 ,再瀏覽器加載網頁時,會選擇對應的模式渲染網頁。
現在我們來測試一下
<div id="divParent" style="padding: 8px; background-color: #aaa; height:1200px; width:300px; overflow:auto" >
<div id="divChild" style="background-color: #0f0;height: 400px; width: 500px; border: solid 10px #f00; position:absolute">
</div>
</div>
<script type="text/javascript">
var divParent = document.getElementsByTagName("body")[0];
divParent.onscroll = function () {
divChild.innerHTML = "";
divChild.style.top = window.pageYOffset + "px";
var scrollwidth = divParent.scrollWidth;
var scrollheight = divParent.scrollHeight;
var scrolltop = divParent.scrollTop;
var scrollleft = divParent.scrollLeft;
var pagexoffset = window.pageXOffset;
var pageyoffset = window.pageYOffset;
var documentelementtop = document.documentElement.scrollTop;
var documentelementleft = document.documentElement.scrollLeft;
var bodyscrolltop = document.body.scrollTop;
var bodyscrollleft = document.body.scrollLeft;
divChild.innerHTML += 'clientWidth: ' + scrollwidth + '<br />';
divChild.innerHTML += 'clientHeight: ' + scrollheight + '<br />';
divChild.innerHTML += 'scrolltop: ' + scrolltop + '<br />';
divChild.innerHTML += 'scrollleft: ' + scrollleft + '<br />';
divChild.innerHTML += 'pagexoffset: ' + pagexoffset + '<br />';
divChild.innerHTML += 'pageyoffset: ' + pageyoffset + '<br />';
divChild.innerHTML += 'documentelementtop: ' + documentelementtop + '<br />';
divChild.innerHTML += 'documentelementleft: ' + documentelementleft + '<br />';
divChild.innerHTML += 'bodyscrolltop: ' + bodyscrolltop + '<br />';
divChild.innerHTML += 'bodyscrollleft: ' + bodyscrollleft + '<br />';
}
</script>
chrome測試結果,我們發現 pagexoffset document.body.scrolltop 可以用,但是注意 我當前的申明了 html5的<!DOCTYPE html>,說明document.documentelement可以用的。

在來看看 firefox的測試效果,同樣申明了文檔類型 這里 document.documentelement可以用,尼瑪真是日了狗了,難道是html5 文檔類型特殊一點,我們測試一下其他類型的文檔類型

但是發現結果和上面的一樣,好吧,不管上面那些了,下面總結如何兼容scrolltop如果是求 scrolltop 可以取 body.scrolltop 和documen.documentelement.scrolltop的max值,這樣不管如何總能取一個正確的值。
我們在上面的章節知道了如何取scrolltop值,接下來我們就來介紹一下dom中的窗口坐標和文檔坐標,
窗口坐標:當前顯示可見的頁面的左上角的坐標(如果出現滾動條,且滾動條發生滾動,則 窗口坐標和文檔坐標不一致,因為窗口坐標只顯示當前顯示的頁面的部分,而文檔可能因為滾動條的緣故遮蓋了);
文檔坐標:垂直滾動條在最上方,沒有滾動,水平滾動條在最左邊,沒有滾動時,時的左上方的坐標
如果沒有滾動條時,窗口坐標和文檔坐標一致。
那如何在窗口坐標和文檔坐標之間進行轉換呢,這里我們就要用到上面的滾動條卷去的高度和坐標的距離,假設,有一個元素在文檔中的y坐標(即垂直方向的)是200px;但是我們通過滾動條向下滾動了75px,那么當前的窗口坐標就為125px;
因此如果scrolltop的值大於0的話 我們窗口的坐標y=文檔的坐標y-scrolltop,
同時視口坐標也有對應的方法可以使用
可以通過調用元素的getBoundingClientRect方法。方法返回一個有left、right、top、bottom屬性的對象,分別表示元素四個位置的相對於視口的坐標。getBoundingClientRect所返回的坐標包含元素的內邊距和邊框,不包含外邊距。兼容性很好,非常好用。
下面貼一段犀牛角上的代碼
得到滾動條值
function getScrollOffsets(w) {
var w = w || window;
//除ie8及更早版本,其他瀏覽器都能使用
if (w.pageXoffset != null) {
return { x: w.pageXoffset, y: pageYoffset };
}
//標注模式ie(或任何瀏覽器)
var d = w.document;
if (document.compatMode == "CSS1Compat")
return { x: d.documentElement.scrollLeft, y: d.documentElement.scrollTop };
//怪異模式下(沒有申明dtd)
return { x: d.body.scrollLeft, y: d.body.scrollTop };
}
通過使用這個函數發現也不是很兼容 在chrome中一直是0,說明即使在標准模型中,,即申明了dtd chrome 也不能取documentElement.scrollLeft值。opera也同樣不能取值,firefox能取值。因此早平常的使用中我還是 使用math.max(docuemnt.body.scrolltop,docuemnt.documentelement.scrolltop)來使用。
好了今天的就介紹到這里。如有錯誤,歡迎各位博客園朋友指正
