【JavaScript】全面解析offsetLeft、offsetTop


 

假設 obj 為某個 HTML 控件。
obj.offsetLeft 指 obj 距離左方或上層控件的位置,整型,單位像素。

obj.offsetRight 指 obj 距離右方或上層控件的位置,整型,單位像素。

obj.offsetTop 指 obj 距離上方或上層控件的位置,整型,單位像素。

obj.offsetBottom 指 obj 距離下方或上層控件的位置,整型,單位像素。

obj.offsetWidth 指 obj 控件自身的寬度,整型,單位像素。

obj.offsetHeight 指 obj 控件自身的高度,整型,單位像素

我們對前面提到的“上方或上層”與“左方或上層”控件作個說明。

例如:
<div id="tool">
<input type="button" value="提交">
<input type="button" value="重置">
</div>

“提交”按鈕的 offsetTop 指“提交”按鈕距“tool”層上邊框的距離,因為距其上邊最近的是 “tool” 層的上邊框。
“重置”按鈕的 offsetTop 指“重置”按鈕距“tool”層上邊框的距離,因為距其上邊最近的是 “tool” 層的上邊框。

“提交”按鈕的 offsetLeft 指“提交”按鈕距“tool”層左邊框的距離,因為距其左邊最近的是 “tool” 層的左邊框。
“重置”按鈕的 offsetLeft 指“重置”按鈕距“提交”按鈕右邊框的距離,因為距其左邊最近的是“提交”按鈕的右邊框。

以上屬性在 FireFox 中也有效。

window.screen.availWidth     返回當前屏幕寬度(空白空間)  
window.screen.availHeight     返回當前屏幕高度(空白空間)  
window.screen.width     返回當前屏幕寬度(分辨率值)  
window.screen.height     返回當前屏幕高度(分辨率值)  
window.document.body.offsetHeight;     返回當前網頁高度  
window.document.body.offsetWidth;     返回當前網頁寬度  

我們這里說說四種瀏覽器對 document.body 的 clientHeight、offsetHeight 和 scrollHeight 的解釋。

這四種瀏覽器分別為IE(Internet Explorer)、NS(Netscape)、Opera、FF(FireFox)。

clientHeight
大家對 clientHeight 都沒有什么異議,都認為是內容可視區域的高度,也就是說頁面瀏覽器中可以看到內容的這個區域的高度,一般是最后一個工具條以下到狀態欄以上的這個區域,與頁面內容無關。

offsetHeight
IE、Opera 認為 offsetHeight = clientHeight + 滾動條 + 邊框。
NS、FF 認為 offsetHeight 是網頁內容實際高度,可以小於 clientHeight。

scrollHeight
IE、Opera 認為 scrollHeight 是網頁內容實際高度,可以小於 clientHeight。
NS、FF 認為 scrollHeight 是網頁內容高度,不過最小值是 clientHeight。

簡單地說
clientHeight 就是透過瀏覽器看內容的這個區域高度。
NS、 FF 認為 offsetHeight 和 scrollHeight 都是網頁內容高度,只不過當網頁內容高度小於等於 clientHeight 時,scrollHeight 的值是 clientHeight,而 offsetHeight 可以小於 clientHeight。
IE、Opera 認為 offsetHeight 是可視區域 clientHeight 滾動條加邊框。scrollHeight 則是網頁內容實際高度。

同理
clientWidth、offsetWidth 和 scrollWidth 的解釋與上面相同,只是把高度換成寬度即可。

再附上一些

網頁可見區域寬: document.body.clientWidth;
網頁可見區域高: document.body.clientHeight;
網頁可見區域寬: document.body.offsetWidth   (包括邊線的寬);
網頁可見區域高: document.body.offsetHeight (包括邊線的寬);
網頁正文全文寬: document.body.scrollWidth;
網頁正文全文高: document.body.scrollHeight;
網頁被卷去的高: document.body.scrollTop;
網頁被卷去的左: document.body.scrollLeft;
網頁正文部分上: window.screenTop;
網頁正文部分左: window.screenLeft;
屏幕分辨率的高: window.screen.height;
屏幕分辨率的寬: window.screen.width;
屏幕可用工作區高度: window.screen.availHeight;
屏幕可用工作區寬度:window.screen.availWidth;

對於因為使用web標准失效比如document.body.scrollTop總是零的原因

解決方法如下:

原來在HTML文件頭部聲明了這樣一句:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

改成這樣就好了:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
但頁面稍有變化,感覺不爽,於是又在google里找,終於發現這是IE5與IE6的區別:

var scrollPos;
if (typeof window.pageYOffset != 'undefined') {
   scrollPos = window.pageYOffset;
}
else if (typeof document.compatMode != 'undefined' &&
     document.compatMode != 'BackCompat') {
   scrollPos = document.documentElement.scrollTop;
}
else if (typeof document.body != 'undefined') {
   scrollPos = document.

 

 

一、第一個小例子

 1 <body>
 2 <style>
 3 body { margin:0;  }
 4 .box1 { width:300px; height:300px; margin:100px; background:#333; overflow:hidden; }
 5 .box2 { width:200px; height:200px; margin:100px; background:#666; overflow:hidden; }
 6 .box3 { width:100px; height:100px; margin:100px; background:#999;}
 7 </style>
 8 <div class="box1">
 9     <div class="box2">
10         <div class="box3"></div>
11     </div>
12 </div>
13 <script>
14     var oBox1 = document.querySelector('.box1');
15     var oBox2 = document.querySelector('.box2');
16     var oBox3 = document.querySelector('.box3');
17     
18     console.log('box1: '+ oBox1.offsetLeft +','+ oBox1.offsetTop);
19     console.log('box2: '+ oBox2.offsetLeft +','+ oBox2.offsetTop);
20     console.log('box3: '+ oBox3.offsetLeft +','+ oBox3.offsetTop);
21 </script>
22 </body>

①第一個例子中,三個div的上一級的定位元素都是body,body是最外層的定位元素,三個div獲取到的offsetLeft值跟offsetTop值都是相對於body的偏移量。

二、第二個小例子(給box1添加相對定位)

<body>
<style>
body { margin:0;  }
.box1 { width:300px; height:300px; margin:100px; background:#333; overflow:hidden; position:relative;}
.box2 { width:200px; height:200px; margin:100px; background:#666; overflow:hidden; }
.box3 { width:100px; height:100px; margin:100px; background:#999;}
</style>
<div class="box1">
    <div class="box2">
        <div class="box3"></div>
    </div>
</div>
<script>
    var oBox1 = document.querySelector('.box1');
    var oBox2 = document.querySelector('.box2');
    var oBox3 = document.querySelector('.box3');
    
    console.log('box1: '+ oBox1.offsetLeft +','+ oBox1.offsetTop);
    console.log('box2: '+ oBox2.offsetLeft +','+ oBox2.offsetTop);
    console.log('box3: '+ oBox3.offsetLeft +','+ oBox3.offsetTop);
</script>
</body>

②第二個例子中,box1加上了相對定位,這時候box2,box3的上一級定位元素不再是body了,這時他們獲取到的offsetLeft值跟offsetTop值都是相對於box1的偏移量。而box1的上一級定位元素還是body,所以他的偏移量還是相對於body的。

三、第三個小例子(給box1,box2添加相對定位)

 1 <body>
 2 <style>
 3 body { margin:0;  }
 4 .box1 { width:300px; height:300px; margin:100px; background:#333; overflow:hidden; position:relative; }
 5 .box2 { width:200px; height:200px; margin:100px; background:#666; overflow:hidden; position:relative; }
 6 .box3 { width:100px; height:100px; margin:100px; background:#999;}
 7 </style>
 8 <div class="box1">
 9     <div class="box2">
10         <div class="box3"></div>
11     </div>
12 </div>
13 <script>
14     var oBox1 = document.querySelector('.box1');
15     var oBox2 = document.querySelector('.box2');
16     var oBox3 = document.querySelector('.box3');
17     
18     console.log('box1: '+ oBox1.offsetLeft +','+ oBox1.offsetTop);
19     console.log('box2: '+ oBox2.offsetLeft +','+ oBox2.offsetTop);
20     console.log('box3: '+ oBox3.offsetLeft +','+ oBox3.offsetTop);
21 </script>
22 </body>

③第三個例子中,box1跟box2都加上了相對定位,這時候,box3的上一級定位元素變成是box2,box2的上一級定位元素是box1,box1的上一級定位元素還是body。所以這時候就出現了。三個div的偏移量都為100;

四、解析

通過上面的三個例子不難看出,offsetLeft值跟offsetTop值的獲取跟父級元素沒關系,而是跟其上一級的定位元素(除position:static;外的所有定位如fixed,relative,absolute)有關系。 

  所以給父級添加定位之后,offset的偏移值就會變成相對於父級的偏移值.(除了position:static;外的所有定位,如fixed,relative,absolute都會使偏移值的參考對象變為父級))

五、擴展(在第三個例子中,假如我想獲取到box3到瀏覽器窗口的偏移量,該怎么去獲取呢?)

思路很簡單,就是把元素本身的偏移量跟所有上級定位元素的偏移量都加起來就可以了,問題又來了,假如我們不知道他有幾個上級定位元素呢?

其實也不難。js不但提供了offsetLeft、offsetTop方法,還提供了offsetParent(獲取上一級定位元素對象)的方法。所以現在我們只需封裝一個函數就可以了。

 

 1 function offset(obj,direction){
 2     //將top,left首字母大寫,並拼接成offsetTop,offsetLeft
 3     var offsetDir = 'offset'+ direction[0].toUpperCase()+direction.substring(1);
 4         
 5     var realNum = obj[offsetDir];
 6     var positionParent = obj.offsetParent;  //獲取上一級定位元素對象
 7         
 8     while(positionParent != null){
 9     realNum += positionParent[offsetDir];
10     positionParent = positionParent.offsetParent;
11     }
12     return realNum;
13 }

運用程序中

 1 <body>
 2 <style>
 3 body { margin:0;  }
 4 .box1 { width:300px; height:300px; margin:100px; background:#333; overflow:hidden; position:relative; }
 5 .box2 { width:200px; height:200px; margin:100px; background:#666; overflow:hidden; position:relative; }
 6 .box3 { width:100px; height:100px; margin:100px; background:#999;}
 7 </style>
 8 <div class="box1">
 9     <div class="box2">
10         <div class="box3"></div>
11     </div>
12 </div>
13 <script>
14     var oBox1 = document.querySelector('.box1');
15     var oBox2 = document.querySelector('.box2');
16     var oBox3 = document.querySelector('.box3');
17         
18     function offset(obj,direction){
19         //將top,left首字母大寫,並拼接成offsetTop,offsetLeft
20         var offsetDir = 'offset'+ direction[0].toUpperCase()+direction.substring(1);
21         
22         var realNum = obj[offsetDir];
23         var positionParent = obj.offsetParent;  //獲取上一級定位元素對象
24         
25         while(positionParent != null){
26             realNum += positionParent[offsetDir];
27             positionParent = positionParent.offsetParent;
28         }
29         return realNum;
30     }
31     console.log('box1: '+ offset(oBox1,'left') +','+ offset(oBox1,'top'));
32     console.log('box2: '+ offset(oBox2,'left') +','+ offset(oBox2,'top'));
33     console.log('box3: '+ offset(oBox3,'left') +','+ offset(oBox3,'top'));
34 </script>
35 </body>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM