存取元素位置



CSS的position屬性可以設定不同的值,代表元素的定位方式,如果沒有設定,大多數元素預設是static,元素依序繪製在文件的流動版面。你還可以設定的值有relativeabsolutefixedinherit

元素的top表示距原點的垂直距離,正值為往下,left表示距原點的水平距離,正值為往右。bottom表示距原點的垂直距離,正值為往上,right表示距原點的水平距離,正值為往左。

absolute表示絕對定位,可以藉由設置元素topleftbottomright來定位,定位是相對於元素的首個非static定位的父元素。在絕對定位時,元素可以堆疊,此時可利用z-index來設定重疊順序,數值越大,表示可以堆壘在越上面,z-index預設是頁面中標籤定義的順序,越後定義的標籤z-index越大。

下面這個範例運用了絕對定位、top、left與z-index屬性,可以使用滑鼠點選改變id為message1的<div>的位置,可以按下某個<div>,使之z-index提高:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<style type="text/css">
#message1 {
color: #ffffff;
background-color: #ff0000;
border-width: 10px;
border-color: black;
border-style: solid;
width: 100px;
height: 50px;
padding: 50px;
margin: 10px;
position: absolute;
top: 50px;
left: 50px;
z-index: 0;
}
#message2 {
color: #ffffff;
background-color: #ff0000;
border-width: 10px;
border-color: black;
border-style: solid;
width: 100px;
height: 50px;
padding: 50px;
margin: 10px;
position: absolute;
top: 150px;
left: 150px;
z-index: 0;
}
</style>
<script type="text/javascript">
window.onload = function(event) {
var message1 = document.getElementById('message1');
var message2 = document.getElementById('message2');

document.onclick = function(event) {
event = event || window.event;
message1.style.left = event.clientX + 'px';
message1.style.top = event.clientY + 'px';
};

function stopPropagation(event) {
if(event) {
event.stopPropagation();
}
else {
window.event.cancelBubble = true;
}
}

message1.onclick = function(event) {
this.style.zIndex = 1;
message2.style.zIndex = 0;
stopPropagation(event);
};

message2.onclick = function(event) {
this.style.zIndex = 1;
message1.style.zIndex = 0;
stopPropagation(event);
};
};
</script>
</head>
<body>
<div id="message1">這是訊息一</div>
<div id="message2">這是訊息二</div>
</body>
</html>

relative 則是表示元素將相對於標準位置擺放,相對值是使用top、left或bottom、right設定。例如,若某元素標準位置為100x50的位置,若設定 該元素的position為relative,而top、left分別設為20、30的話,則元素最後的位置就是在(100+20)x(50+30)= 120x80的位置。

fixed則是以瀏覽器視埠(
view-port)為基準點。例如,你想要讓某個元素在捲動後,依舊可以在可視畫面中的100x50的位置,則可以將position設為fixed,此時top、left與bottom、right就是相對於可視畫面。在Internet Explorer 6瀏覽器中不支援,Internet Explorer 7/8只有在指定<!DOCTYPE>時才支援,

要取得元素的確實位置,必須知道offsetParent為何,offsetParent並非元素的直接父節點,而是在元素的所有父階層中,第一個可用來作為位置參考的節點。

每個元素都可以取得offsetTopoffsetLeft,分別代表距offsetParent外邊框左上角的距離,所以,在簡單的排版下,想要知道元素在版面中的確實位置,基本上可以如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<style type="text/css">
#container {
color: #ffffff;
background-color: #ff0000;
border-width: 10px;
border-color: black;
border-style: solid;
width: 100px;
height: 50px;
padding: 50px;
position: absolute;
top: 50px;
left: 50px;
}
#message {
position: static;
top: 20px;
left: 20px;
}
</style>
<script type="text/javascript">
window.onload = function(event) {
function offset(element) {
var x = 0;
var y = 0;
while(element) {
x += element.offsetLeft;
y += element.offsetTop;
element = element.offsetParent;
}
return {
x: x,
y: y,
toString: function() {
return '(' + this.x + ', ' + this.y + ')';
}
};
}

document.onclick = function(event) {
event = event || window.event;
var container = document.getElementById('container');
container.style.left = event.clientX + 'px';
container.style.top = event.clientY + 'px';
var message = document.getElementById('message');
var console = document.getElementById('console');
console.innerHTML = offset(message);
};
};
</script>
</head>
<body>
<div id="container"><span id="message">這是一段訊息<span></div>
<span id="console"></span>
</body>
</html>

一個需要元素確實位置的例子,就是像搜尋框中出現的提示,你需要知道搜尋框的位置,將傳回的關鍵字建議顯示在搜尋框下方。下面這個例子是個簡單示範:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN">
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="content-type">
<style type="text/css">
#container {
color: #ffffff;
background-color: #ff0000;
height: 50px;
position: absolute;
top: -100px;
left:-100px;
}
</style>
<script type="text/javascript">
window.onload = function(event) {
function offset(element) {
var x = 0;
var y = 0;
while(element) {
x += element.offsetLeft;
y += element.offsetTop;
element = element.offsetParent;
}
return {
x: x,
y: y,
toString: function() {
return '(' + this.x + ', ' + this.y + ')';
}
};
}
var input = document.getElementById('search');
var search = offset(input);
var container = document.getElementById('container');
container.style.left = search.x + 'px';
container.style.top = search.y + input.offsetHeight + 'px';
container.style.width = input.offsetWidth + 'px';
};
</script>
</head>
<body>
<div id="container">這是一段訊息</div>
<hr>
搜尋:<input id="search" type="text">
</body>
</html>

不幸地,offsetParent存在瀏覽器差異性,在
Firefox上,就absolute、fixed的元素而言,offsetParent是<body>標籤,就static、relative而言,就是元素的所有父階層中,第一個可用來作為位置參考的節點,但relative的設定不同的Internet Explorer版本上,所取得的offsetParent各不相同

另外,在更複雜的排版下,取得元素精確位置所要考慮的事情會更複雜,例如,
CSS的overflow設定可建立捲軸,偏移量不會考慮捲軸位置,如果使用了overflow設定,必須再考慮捲軸值。例如:
function offset(element) {
    var x = 0;
    var y = 0;
    for(var e = element; e; e = e.offsetParent) {
        x += e.offsetLeft;
        y += e.offsetTop;
    }

          //  修正捲軸區域的量
    for(var e = element.parentNode; e && e != document.body; e = e.parentNode) {
        if(e.scrollLeft) {
            x -= e.scrollLeft;
        }
        if(e.scrollTop) {
            y -= e.scrollTop;
        }
    }

    return {
        x: x,
        y: y,
        toString: function() {
            return '(' + this.x + ', ' + this.y + ')';
        }
    };
}