使用位置、尺寸和可见性基本就可以在现代浏览器中模拟绝大多数常见的用户效果了。元素的位置是实现交互效果的基础。在CSS中,元素使用偏移量来定位,它是通过元素到它父元素的左上角的偏移量来计算。CSS的坐标系如下图

页面上的所有元素都有left(水平位置)和top(垂直位置)的偏移量。为了更好理解这一点,先了解一下CSS的定位方式。基础的HTML代码是:
<html>
<head>
<style>
p {
border: 3px solid red;
padding: 10px;
width: 400px;
background: #FFF;
}
p.odd {
/* 定位信息 */
position: static;
top: 0px;
left: 0px;
}
</style>
</head>
<body>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Etiam ...</p>
<p class='odd'>Phasellus dictum dignissim justo. Duis nec risus id nunc ...</p>
<p>Sed vel leo. Nulla iaculis, tortor non laoreet dictum, turpis diam ...</p>
</body>
</html>
通过对第二个段落的定位,分析一下CSS的定位方式。
□ 静态定位:这是默认方式。它遵循文档的普通流动(flow)。当静态定位中,top和left属性无效。下图的定位代码是 position:static; top:0px; left:0px; 的效果:

□ 相对定位:和静态定位类似,同样遵循文档的普通流动。如果设置了top和left属性则会产生相应的偏移。下图的定位代码是:position:relative; top:-50px; left:50px;

□ 绝对定位:绝对定位会使元素完全跳出页面布局的普通流动,会相对于它的第一个非静态定位的祖先元素而定位。如果没有这样的祖先元素,则相对于整个文档。下图的定位代码是:position:absolute; top:20px; left:0px;

□ 固定定位:固定定位相对于浏览器窗口而定位。设置top和left为0会使它在浏览器的左上角显示,而且不受滚动条的影响。下图的定位代码是:position:fixed; top:20px; right:0px;

获取位置
元素的位置取决于CSS设置,同时又受其它因素的影响。所以单纯的访问CSS属性并不能获取元素的精确位置。为了获取元素相对于页面的位置,有一些CSS属性可以利用,在现代浏览器中都支持以下3个属性:
□ offsetParent : 理论上,这是元素的父元素,元素相对于它定位
□ offsetLeft 和 offfsetTop : 在 offsetParent 环境中的水平和垂直偏移量
为了获取元素相对于页面的精确位置,可以遍历DOM,使用offsetParent属性并累加它们的偏移量来计算元素的位置。下面是连个确定元素相对于整个文档的x和y位置的辅助函数:
// 获取元素的水平位置
function pageX(elem) {
var p = 0;
// 累加每一个父元素的偏移量
while ( elem.offsetParent ) {
// 增加偏移量
p += elem.offsetLeft;
// 遍历下一个父元素
elem = elem.offsetParent;
}
return p;
}
// 获取元素的垂直位置
function pageY(elem) {
var p = 0;
// 累加每一个父元素的偏移量
while ( elem.offsetParent ) {
// 增加偏移量
p += elem.offsetTop;
// 遍历下一个父元素
elem = elem.offsetParent;
}
return p;
}
接下来是获取元素相对于它的父元素的水品和垂直位置。简单地使用 style.left 或 style.top 并不够,因为需要处理的元素可能尚未经过JavaScript或CSS的格式化。要找到元素相对于它的父元素的位置,可以利用offsetParent属性,但该属性并不保证能够反追指定元素的真实父元素,所以还需要使用前面的pageX和pageY函数来计算父元素和子元素之间的差。在下面的函数中,如果是当前元素的父元素,则使用offsetParent;否则继续遍历DOM,使用pageX和pageY函数来确定它的真实位置。
// 获取相对于父元素的水平位置
function parentX(elem) {
// 如果 offsetParent 是元素的父元素,则返回
return elem.parentNode == elem.offsetParent ?
elem.offsetLeft :
// 否则计算元素和其父元素的水平差值
pageX( elem ) - pageX( elem.parentNode );
}
// 获取相对于父元素的垂直位置
function parentY(elem) {
// 如果 offsetParent 是元素的父元素,则返回
return elem.parentNode == elem.offsetParent ?
elem.offsetTop :
// 否则计算元素和其父元素的水平差值
pageY( elem ) - pageY( elem.parentNode );
}
最后是获取元素相对于它的CSS容器的位置。在CSS定位方式的讨论中我么知道,即使元素包含在另一个元素内,它也可以相对于其他的父元素定位(使用相对和绝对定位)。这种情形可以使用getStyle函数得到CSS偏移的最终值,这等于元素的位置值。
// 左侧位置
function posX(elem) {
// 获取样式并得到数值
return parseInt( getStyle( elem, "left" ) );
}
// 顶端位置
function posY(elem) {
// 获取样式并得到数值
return parseInt( getStyle( elem, "top" ) );
}
设置位置
调整元素位置的唯一方法就是修改它的CSS属性,仅需要修改left和top属性即可(尽管还有right和bottom属性)。这样就可以设置元素的位置,不管元素的当前位置在哪儿里。
// 设置元素的水平位置
function setX(elem, pos) {
// 设置CSS的 'left' 属性
elem.style.left = pos + "px";
}
// 设置元素的垂直位置
function setY(elem, pos) {
// 设置CSS的 'top' 属性
elem.style.top = pos + "px";
}
最后,实现一对函数用来增加相对于当前位置的偏移量。利用这个函数可以调整元素的位置向上偏移5像素,从而实现各种动画效果。
// 增加水平偏移量
function addX(elem,pos) {
setX( posX(elem) + pos );
}
// 增加垂直偏移量
function addY(elem,pos) {
setY( posY(elem) + pos );
}
转载请注明:陈童的博客 » JavaScript与CSS — 元素的位置