對於div的offsetLeft或offsetTop屬性,它與postion的關係十分密切。
默認情況下是position:static;在position爲static(即沒有設置positoin屬性,或position爲空時)。
1.在ie7(ie6沒有環境測試估計一樣)中,div的offsetLeft的值是當前div左邊框到它父級div左內邊框的像素距離,對於它的父級div的position對它的結果沒有影響。
2.在ie8,ie9,firefox,chorme中,祖先級的position對這個結果的影響是明顯的,因爲div的offsetLeft的值是當前div左邊框到它祖先級中第一個帶position:relative;或position:absolute屬性的元素的像素距離。
以下代碼在ie7,ie8,ie9,firefox,chrome下證明了這一點
<body style="margin:0px;">
<div style="margin-left:30px; margin-top:50px; width:300px; height:300px; background-color:#330000; position:absolute;" οnclick="alert('2:'+this.offsetLeft);">
<div style="margin-left:30px; margin-top:50px; width:200px; height:200px; background-color:#333300;" οnclick="alert('1:'+this.offsetLeft);">
<div style="margin-left:30px; margin-top:50px; width:100px; height:100px; background-color:#ff0000;" οnclick="alert('0:'+this.offsetLeft);"></div>
</div>
</div>
</body>
postion:relative(或absolute)來時,ie7,ie8,ie9,firefox,chrome下的表示是一致的。
position:relative;的div的offsetLeft的取值,與其祖先級div的postion值密切相關。如果position:relative;的div的祖先div都是postion:static;的話,那麼這個div的offsetLeft的值就是當前div左邊框到body的像素距離了,如果祖先div中有postion:relative;或position:absolute;的div,則當前div的offsetLeft的值就是當前div左邊框到距離當前div最近的帶有postion:relative;或position:absolute的祖先的像素距離。
在margin不爲auto時。
當margin爲auto時,ie7和ie8,ie9,firefox,chrome表現出來的結果是很不一樣的。以下是我的測試代碼一:
<body style="margin:0px;">
<div style="margin:auto; width:300px; height:300px; background-color:#330000;" οnclick="alert(this.offsetLeft);">
<div style="margin:auto; width:200px; height:200px; background-color:#333300;" οnclick="alert(this.offsetLeft);">
<div style="margin:auto; width:100px; height:100px; background-color:#ff0000; position:relative;" οnclick="alert(this.offsetLeft);"></div>
</div>
</div>
</body>
此時在ie7上的表現跟我最開始的描述是一致的,就是說margin對ie的offsetLeft是沒有任何影響的。但是在ie8,ie9,firefox,chrome下的表現就奇怪了。點擊最裏層的div,彈出的數依次是670,620,570這說明了加了margin:auto;後div的offsetLeft的取值直接就是當前div到body的距離。事實真是所有的帶margin:auto的div的offsetLeft都是以body爲參照取值嗎?我覺得不可能,於是又改了代碼,如下:
<body style="margin:0px;">
<div style="margin:auto; width:300px; height:300px; background-color:#330000;" οnclick="alert(this.offsetLeft);">
<div style="margin:auto; width:200px; height:200px; background-color:#333300; position:relative;" οnclick="alert(this.offsetLeft);">
<div style="margin:auto; width:100px; height:100px; background-color:#ff0000;" οnclick="alert(this.offsetLeft);"></div>
</div>
</div>
</body>
再點擊最裏層的div,彈出的數依次是
50,620,570
這裏的表現直接就說明了ie8,ie9,firefox,chrome下,加了margin:auto;的div的offsetLeft的取值與position:relative的取值是一樣的,但是加了margin:auto;的div不等於於position:relative的div,一個重要的依據是帶position:relative的div(或是margin:auto;)在實際計算中不把margin:auto;的祖先當做計值參照。所以這裏在記憶上可能會造成混亂。
總結:帶margin:auto的div在計算offsetLeft時與position:relative是一樣的,但是被計算是不按postion:relative看待,以實際position爲準。
這個原因可能會造成ie8,ie9,firefox,chrome不能定位。
關於margin:auto;ie8,ie9,firefox,chrome下的再補充,上面的例子還不夠說明margin:auto在ie8,ie9,firefox,chrome下的一些特殊性,
以下是新測試代碼一:
<body style="margin:0px;">
<div id="d1" style="margin:auto; width:300px; height:300px; background-color:#330000;" οnclick="alert(this.offsetLeft);">
<div id="d2" style="width:250px; height:250px; background-color:#003333; margin-left:15px;" οnclick="alert(this.offsetLeft);">
<div id="d3" style="margin:auto; width:200px; height:200px; background-color:#333300;" οnclick="alert(this.offsetLeft);">
<div id="d4" style="width:100px; height:100px; background-color:#ff0000; margin-left:10px;" οnclick="alert(this.offsetLeft);"></div>
</div>
</div>
</div>
</body>
點擊d4後依次彈出的數值是:620,610,585,570
這裏是讓我產生margin:auto在ie8,ie9,firefox,chrome下對offsetLeft的影響不止於以上所說的例子。照理說d4應該是10而不應該是620,但是它是620,說明ie8,ie9,firefox,chrome對margin:auto;div的子孫級div也是有特殊處理的。於是改變代碼如下,新測試代碼二:
<div id="d1" style="margin:auto; width:300px; height:300px; background-color:#330000;" οnclick="alert(this.offsetLeft);">
<div id="d2" style="width:250px; height:250px; background-color:#003333; margin-left:15px; position:relative;" οnclick="alert(this.offsetLeft);">
<div id="d3" style="margin:auto; width:200px; height:200px; background-color:#333300;" οnclick="alert(this.offsetLeft);">
<div id="d4" style="width:100px; height:100px; background-color:#ff0000; margin-left:10px;" οnclick="alert(this.offsetLeft);"></div>
</div>
</div>
</div>
點擊d4後依次彈出的數值是:35,25,585,570
d4把帶有屬性position:relative的d2,當做offsetLeft的參照做計算了。
於是,反覆更改代碼測試,最後得出一個更完善的結論:
ie8,ie9,firefox,chrome下,帶margin:auto的div在計算offsetLeft時與position:relative是一樣的,但是被計算是不按postion:relative看待,以實際position爲準;並且margin:auto;的div的子孫div都有如上相同的特性(其實就是繼承);
以上的論述,會造成ie8,ie9,firefox,chrome下計算定位的難度,以下是我寫的用於定位的js:
function L_getpos(obj)
{
var left=0;
var top=0;
var oleft=obj.offsetLeft;
var otop=obj.offsetTop;//oleft,otop原點座標
var rleft=0;
var rtop=0;//position:relative的祖先元素的offsetLeft和offsetTop的累計和
var relative=false;//與position相關,如果遇到父級的屬性爲relative或absolute時,此屬性爲true,爲true之後的left和top取值,只取position爲relative或absolute的div的offsetLeft和offsetTop
var marginAuto=false;//祖先級中有沒有margin:auto的屬性,ie8,ie9,firefox,chrome是重要的判斷
var parentNode=obj;
do{
if(getCss(parentNode,"position")=="relative" || getCss(parentNode,"position")=="absolute")
{
relative=true;
}
if((getCss(parentNode,"margin")).indexOf("auto")>=0)
{//這裏有個bug,firefox下如果把margin屬性寫在css文件中的話,沒有辦法獲取這個屬性,會造成計算結果不準
marginAuto=true;
}else{//chrome的兼容
if(getCss(parentNode,"marginLeft")==getCss(parentNode,"marginRight"))
{
marginAuto=true;
}
}
if(!relative)
{
left+=parentNode.offsetLeft;
top+=parentNode.offsetTop;
}else{
if(getCss(parentNode,"position")=="relative" || getCss(parentNode,"position")=="absolute")
{
rleft+=parentNode.offsetLeft;
rtop+=parentNode.offsetTop;
}
}
parentNode=parentNode.parentNode;
}
while(parentNode.tagName.toLowerCase()!="body")
var hack=document.getElementById("__hack__");
var firfoxchromeie8ie9=false;//判斷瀏覽器
if(hack==null)
{
var hackHtml=document.createElement('<div style="background-color:#000000; background-color:#888888\\0; background-color:#999999\\9\\0; *background-color:#777777; _background-color:#666666;" id="__hack__" ></div>');
document.getElementsByTagName("body")[0].appendChild(hackHtml);
hack=document.getElementById("__hack__");
}
var version=hack.style.backgroundColor;
if(version=="#000000" || version=="rgb(0, 0, 0)" || version=="#888888" || version=="rgb(153, 153, 153)")
{
firfoxchromeie8ie9=true;
}
if(firfoxchromeie8ie9 && (relative || marginAuto))
{
left=oleft+rleft;
top=otop+rtop;
}else if(relative){
left+=rleft;
top+=rtop;
}
return {left:left,top:top};
}
function getCss(obj, prop) { //IE中使用的是obj.currentStyle方法,而FF是用的是getComputedStyle 方法
//if(typeof(obj.style[prop])!="undefined")
if(obj.style[prop]!="")
{
return obj.style[prop];
}
if (obj.currentStyle) { //判斷IE
return obj.currentStyle[prop];
}
else if (window.getComputedStyle) { //判斷FF
propprop = prop.replace (/([A-Z])/g, "-$1");
propprop = prop.toLowerCase ();
return document.defaultView.getComputedStyle (obj,null)[prop];
}
return null;
}
這裏會有個bug,在firefox下,如果margin:auto;被寫在外部文件中的話,那麼目前據我所知沒有辦法準確地去判斷當前元素有沒有margin:auto;屬性。避免出錯的方法就是在所有帶margin:auto的元素中加入position:relative;
唉,坑爹了。。。今天才發現有個叫offsetparent的東西!!!!這個可以完美解決我上述說得如此複雜的東西,
offsetParent:是指元素最近的定位(relative,absolute)祖先元素,如果沒有祖先元素是定位的話,會指向body元素
作用:元素的偏移量(offsetLeft,offsetTop)就是以這個祖先元素爲參考點的
原本就是很簡單的東西,非給自己複雜化了。