论坛首页 Web前端技术论坛

offsetXx 探讨

浏览 3844 次
锁定老帖子 主题:offsetXx 探讨
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-05-06   最后修改:2011-06-30
CSS

offsetParent 作为 CSSOM 的一部分,在 IE,FIREFOX 中表现不一致性,因为这点区别很少用到,所以资料一般较少提及。

 

offsetTop,offsetLeft 等 IE,FIREFOX 是通用的,只不过相对的 offsetParent 不同。


updated : 09-05-20


offsetTop firefox ie 并不太相同,


offsetTop firefox 为 从子元素 的顶 padding edge 相对 offsetParent border 底的值


offsetTop ie为 从子元素 的顶border 相对 offsetParent padding 底 的值


updated :2010-11-25


offsetParent 等属性详细可参见 CSSOM规范 。offsetLeft,offsetTop 也可查阅这里

 

因此才有了这一段通用的求页面绝对坐标的方法。(大概,推荐是避免使用该方法 )

 

while (p) {

                x += p.offsetLeft;
                y += p.offsetTop;
                p = p.offsetParent;
            }

 


另外在设置一个任意定位元素到指定页面绝对坐标时,offset 系列属性也起到了不小的作用。详见: 简析 Ext.Element.setXY() 机理

 

这篇文章探讨一下,ie firefox 下面 offsetParent 的不同之处。

 

假设当前元素为 el

 

1.position : relative ,

 

offsetParent 为它的已定位父元素,即 el.parent('*{position!=static}'),IE FIREFOX 通用,区别是 firefox offsetParent 最多到 body 结点,而 IE 到 html 结点。

 

2.position: absolute ,

 

offsetParent 为它的已定位父元素。即 el.parent('*{position!=static}'),这时 el.offsetTop == el.style.top (若 设置了 el.style.top),IE FIREFOX 通用,区别是 firefox offsetParent 最多到 body 结点,而 IE 到 html 结点。


3.position : static || ''

 

  3.1 FIREFOX offsetParent 为它的已定位父元素,即 el.parent('*{position!=static}') ,最多查找到 body。


  3.2 IE offsetParent 为它的具有 layout 的父元素或者已定位父元素,即 el.parent('*{position!=static} ||   layout'),注意 layout 为 ie 的 私有属性,详见: On having layout ,这时最多查找到 body 结点 而不是 html 结点。


PS:一点备忘


ie offsetParent 有的情况下为 html,但是计算 offsetTop 时是从 body 开始计算的,并且 body 和 html 在 ie 中相差 1 像素,即使 html,body {margin:0;padding:0;}

 

实验代码 :

 

注意 i_am_relative6

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" id='HTML'>
<head>
<title>探索offsetParent</title>
</head>
<body id='my_body'>
	

	<div id='i_am_relative' style='position:relative'>
		
		
		<div  id='i_am_noposition_parent' style='zoom:1'> 
			
			<div id='i_am_absolute' style='position:absolute;top:100px;'>
				haha , i am absolute
		</div>
		</div>
	</div>
	
	
	<div id='i_am_relative21' style='position:relative'>
		
		
		<div  id='i_am_noposition_parent22'> 
			
			<div id='i_am_absolute23' style='position:absolute;top:100px;'>
				haha , i am absolute
		</div>
		</div>
	</div>
	
	
	
	<div id='i_am_relative2' style='position:relative'>
		
		
		<div  id='i_am_noposition_parent2'> 
			
			<div id='i_am_noposition'>
				haha , i am noposition
		</div>
		</div>
	</div>
	
	
	
	<div id='i_am_relative3' style='position:relative'>
		
		
		<div  id='i_am_absolute3' style='position:absolute;'> 
			
			<div id='i_am_absolute4' style='position:absolute;top:200px;'>
				haha , i am absolute4
		</div>
		</div>
	</div>
	

	<div id='i_am_relative5' >
			
		<div  id='i_am_not_relative5' style='width:100px;height:100px;border:1px solid green;overflow:hidden;float:left;'> 
			
			<div id='i_am_relative6' style='position:relative;top:100px;'>
				haha , i am relative6
			</div>
		
		
		</div>
		
		
	</div>
	
	
	
	<div id='i_am_nothing9' >
		
		
		<div  id='i_am_nothing8' style='zoom:1;width:100px;height:100px;'> 
			
			<div id='i_am_nothing7' >
				haha , i_am_nothing7
			</div>
		
		
		</div>
		
		
	</div>
	
	
	
	<div id='i_am_nothing10' >
		
		
		<div  id='i_am_nothing11'> 
			
			<div id='i_am_nothing12' >
				haha , i_am_nothing12
			</div>
		
		
		</div>
		
		
	</div>
	
	
	<script type='text/javascript'>
		
		
		function off(el){
			el=document.getElementById(el);
			return el.id+' position:'+ el.style.position+'\n\n offsetParent :'+el.offsetParent+'\n offsetParent id:'+
			(el.offsetParent&&el.offsetParent.id)+'\n'
			+' offsetTop:'+el.offsetTop+'\n offsetParent position:'+(el.offsetParent&&el.offsetParent.style.position)+'\n\n parentNode :'+el.parentNode+'\n parentNode id:'
			+el.parentNode.id+'\n parentNode position:'+el.parentNode.style.position;
		}
		
		
		
		window.onload=function(){
		alert(off('my_body'));
		alert(off('i_am_absolute'));
		
		alert(off('i_am_absolute23'));
		
		alert(off('i_am_noposition'));
		alert(off('i_am_absolute4'));
		
		
		alert(off('i_am_relative6'));
	
		alert(off('i_am_nothing7'));
		
		alert(off('i_am_nothing12'));
		
	};
		</script>
</body>
</html>

 

ps: 一篇比较好的分析

http://www.cnblogs.com/rainman/archive/2009/02/15/1391056.html



在学习offset的相关属性前,必须明确指出offsetHeight/Width、offsetTop/offsetLeft等返回的都是只读的并且以数字的形式返回像素值(例如,返回12,而不是'12px')。

定位父元素 : 指在CSS中某一元素domElement[position:relative/absolute] 所相对定位的元素。

1、offsetParent

   对于offsetParent来讲,最重要的是能够知道 domElement.offsetParent 指向的是哪个元素。然而对于这一点不同的浏览器之间有一些微妙的差异。

   a、domElement设置了position:relative/absolute属性:

      domElement.offsetParent指向的是该元素的定位父元素。

      但也有一个bug,见一下代码:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Rain Man</title>
<style type="text/css">
#target{ position:relative; }
</style>
<script type="text/javascript">
window.onload = function(){
    var target = document.getElementById('target');
    alert(target.offsetParent == document.documentElement);        //IE中指向<html>元素
    alert(target.offsetParent == document.body);    //FF、Safari等指向<body>元素
};
</script>
</head>

<body>
<div id="outer" class="test">
    <div id="inner">
        <div id="target" class="test">Target<br />rainman</div>
    </div>
</div>
</body>
</html>
 

b、domElement没有设置position:relative/absolute,即static:

      这一点所有的浏览器基本相同,domElement的offsetParent指向的是离domElement最近的拥有 position:relative/absolute属性的父级元素。若不存在,则指向 <body>元素。但这种情况也有例外,如果domElement是<td>则 offsetparent 指向<table>

  
c、关于offsetParent的实例:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Rain Man</title>
<style type="text/css">
#outer { position:absolute;}
</style>
<script type="text/javascript">
window.onload = function(){
    var target = document.getElementById('target');
    var outer = document.getElementById('outer');
    alert(target.offsetParent == outer);    //true
};
</script>
</head>

<body>
<div id="outer" class="test">
    <div id="inner">
        <div id="target" class="test">Target<br />rainman</div>
    </div>
</div>
</body>
</html>
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Rain Man</title>
<style type="text/css">
</style>
<script type="text/javascript">
window.onload = function(){
    var target = document.getElementById('target');
    alert(target.offsetParent == document.body);    //true
};
</script>
</head>

<body>
<div id="outer" class="test">
    <div id="inner">
        <div id="target" class="test">Target<br />rainman</div>
    </div>
</div>
</body>
</html>
 

2、offsetLeft/Top

offsetLeft: 该元素左border的左边缘  到  该元素的offsetParent的左border内边缘的水平距离。

offsetTop:该元素的上border的上边缘  到  该元素的offsetParent的上border内边缘的垂直距离。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Rain Man</title>
<style type="text/css">
*{margin:0px; padding:0px;}
.test{
    padding:5px;
    margin:10px;
    color:#fff;
    border:7px solid #000;
    background-color:#CC66FF;
}
#target{
    position:absolute;
    left:3px;
    top:9px;
    width:100px;
    height:100px;
}
#outer{
    position:relative;
    width:300px;
    height:300px;    
}
</style>
<script type="text/javascript">

window.onload = function(){
    var target = document.getElementById('target');
    alert(target.offsetLeft);    //13 = margin-10px + left-3px
};
</script>
</head>

<body>
<div id="outer" class="test">
    <div id="inner">
        <div id="target" class="test">Target<br />rainman</div>
    </div>
</div>
</body>
</html>

 

3、offsetWidth/offsetHeight

   给出元素在页面中占据的宽度和高度的总计。注意:把元素的边框和滚动条计算在内。

   offsetWidth =  border-left-width + padding-left + width + padding-right + border-right-width;

   offsetHeight =  border-top-width + padding-top + height + padding-bottom + border-bottom-width; 


4、相关应用

a、获得一个元素的实际宽度和高度 ,例如:一个自适应高度的段落,往往可以通过获得该元素CSS层叠后的最终高度【见下代码】,但是这种方法在IE中有时返回的是auto,所以使用一个元素的offsetWidth/offsetHeight是比较理想的方法。

 

function getStyle(elem , type){
    var typeface = '';
    if(elem.currentStyle)
        typeface = elem.currentStyle[type];
    else if(window.getComputedStyle)
        typeface = window.getComputedStyle(elem , null)[type];
    return typeface;        
}

 

 

获得一个元素位置的可移植的方法:在窗口中的位置

 

function getX(elem){
    var x = 0;
    while(elem){
        x = x + elem.offsetLeft;
        elem = elem.offsetParent;
    }
    return x;
}
function getY(elem){
    var y = 0;
    while(elem){
        y = y + elem.offsetTop;
        elem = elem.offsetParent;
    }
    return y;
}
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics