offsetTop/offsetLeft/offsetParentの闇
簡単な定義
- 要素のoffsetLeftプロパティ
- 要素の左辺と、offset基準要素の左辺との距離(px)
- 要素のoffsetTopプロパティ
- 要素の上辺と、offset基準要素の上辺との距離(px)
- 要素のoffsetParentプロパティ
- 要素のoffset基準要素(これが何になるかが問題)
○結論から先に見たい方は>>こちら<<○
いままで、なんとなくoffsetTopやoffsetLeftを使っていました^^; これらは「ページ上の要素の位置」を格納してると思って。しかし、よくよく調べてみるとそれは誤りであり、かつかなり複雑でややこしいプロパティであることが分かってきました。*1
もともと、(ここでは述べませんが、offsetHeightとoffsetWidthも含め)offset〜のプロパティはIEがVer5で独自に実装したものらしく、その後他のブラウザが追随して実装したようです。しかし、その実装方法はバラバラになってます・・・。
とりあえず、サンプルを示します。prototype.jsを使用しています。同一ディレクトリにprototype.jsを配置してください(ダウンロードはこちら)。
2006/10/24 追記。更に詳細なサンプルを>>下<<に作成しました。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><!--Quirks mode--> <!--<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">--><!--Standards mode--> <html> <head> <title></title> <style> body{ /*Opera以外は入れると正しく取れなくなる・・・*/ /*border:solid blue 2px;*/ } .mark{ background-color:red; width:50px; height:50px; } .rel{ position:relative; left:100px; top:20px; } .abs{ position:absolute; } #mark0{ left:200px; top:20px; } #parent2{ left:400px; top:450px; } .parent{ border:solid blue 2px; width:200px; height:150px; } .child{ background-color:yellow; width:160px; height:120px; } .child_n{ background-color:yellow; } </style> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> function test(){ var ary = []; (9).times(function(index){ ary.push($('mark' + index)); }); var str = "<table border><tr><th>id</th><th>offsetLeft</th>" + "<th>offsetTop</th><th>offsetParent</th></tr>"; str += ary.inject("", function(memo, value, index){ var op = value.offsetParent; var id = ""; if(op == document.body.parentNode){ id = "[HTML]" }else{ id = op.id; } memo += "<tr><td>" + value.id + "</td>"; memo += "<td>" + value.offsetLeft + "</td>"; memo += "<td>" + value.offsetTop + "</td>"; memo += "<td>" + id + "</td></tr>"; return memo; }); str += "</table>"; Element.update('view', str); } function change(obj){ var ccn = (obj.checked) ? "child" : "child_n"; var cary = []; (3).times(function(index){ cary.push(new Element.ClassNames('child' + index)); }); cary.invoke('set', ccn); } </script> </head> <body id="body">body <div id="mark0" class="mark abs">mark0<br>abs</div> <div id="mark1" class="mark rel">mark1<br>rel</div> <div id="mark2" class="mark">mark2</div> <div id="parent0" class="parent">parent0 <div class="child" id="child0">child0 <div id="mark3" class="mark rel">mark3<br>rel</div> <div id="mark4" class="mark">mark4</div> </div> </div> <div id="parent1" class="parent rel">parent1 rel <div class="child" id="child1">child1 <div id="mark5" class="mark rel">mark5<br>rel</div> <div id="mark6" class="mark">mark6</div> </div> </div> <div id="parent2" class="parent abs">parent2 abs <div class="child" id="child2">child2 <div id="mark7" class="mark rel">mark7<br>rel</div> <div id="mark8" class="mark">mark8</div> </div> </div> <div style="position:absolute;top:50px;left:400px;"> <button id="test" onclick="test();">TEST</button> <input type="checkbox" onclick="change(this);" checked/> <div id="view"></div> </div> </body> </html>
TESTボタンを押すと、要素mark0〜10とtd1のoffsetLeft、offsetTop、offsetParentを表示します。
各要素の主な条件は以下。
ID | 条件 |
---|---|
mark0 | body直下に記述。position:absolute;指定 |
mark1 | body直下に記述。position:relative;指定 |
mark2 | body直下に記述。position指定なし |
mark3 | 要素parent1(position指定なし)の子要素。position:relative;指定 |
mark4 | 要素parent1(position指定なし)の子要素。position指定なし |
mark5 | 要素parent2(position:relative;)の子要素。position:relative;指定 |
mark6 | 要素parent2(position:relative;)の子要素。position指定なし |
mark7 | 要素parent3(position:absolute;)の子要素。position:relative;指定 |
mark8 | 要素parent3(position:absolute;)の子要素。position指定なし |
実際にはそれぞれ要素child*が存在します。
基礎知識 position:absolute|relative|static;について(2006/10/16追記)
本題に入る前に、ちょっと確認。
style.positionの値とその効果
- static(デフォルト)
- 通常配置。その要素のstyle.position, left, top以外の要因で決定される位置に配置される。つまりはフツーの配置。
- relative
- 相対配置。上記通常配置からstyle.top, leftの値分ずらして配置する。relative化した要素は、他の要素配置時、元の位置にあるものとして扱われる(元の位置に他の要素が流れ込まない)。
- absolute
- 絶対配置。基準位置からstyle.top, leftの値分ずらして配置する*2。absolute化した要素は他の要素配置に影響しない(元の位置に他の要素が流れ込む)。
ほぼ常識です。ただ、ちょっと気をつけなければいけないのは、position:absolute;時の「基準位置」です。大抵、ページの左上端という認識だと思います。実は、これが少し曲者です。
基準位置は以下のように決まります。
- ノードツリー上方で直近のposition:absolute;、position:relative;の要素の枠線内側左上端。
- 以上に該当がなければページの左上端。
これはダブルスタンダードな気がします。前者の「ノードツリー上方の〜」という要素は、後述しますがoffsetParentに同じになるケースが多いです。その要素内の位置なので、top、leftの値が変わらなくても、marginの値が変わると表示位置が変わります。一方、後者のoffsetParentはbody要素になるケースが多いのですが、その場合、body要素のmarginを変更しても表示位置は変わりません。この点は注意が必要です。
2006/12/14 コメントいただいて気が付いたのですが、absolute時(というか全般的に)、(内側の)要素側の基準は要素のmarginを含めた左上端なんですね。枠線外側だと勘違いしてました。
2009/07/29 CSSでの基準要素側の基準を、「コンテンツ」(margin、border-width、padding含まない)としていたのを、「枠線内側」(paddingは含む)に修正しました。
Netscape7.1 Firefox1.5.0.4
素直な動作をするNetscapeとFirefoxを最初に見ていきます。
- 上記例の実行結果
id | offsetLeft | offsetTop | offsetParent |
---|---|---|---|
mark0 | 200 | 20 | body |
mark1 | 108 | 47 | body |
mark2 | 8 | 77 | body |
mark3 | 110 | 188 | body |
mark4 | 10 | 218 | body |
mark5 | 100 | 58 | parent1 |
mark6 | 0 | 88 | parent1 |
mark7 | 100 | 58 | parent2 |
mark8 | 0 | 88 | parent2 |
mark0〜4まではoffsetParentはbody要素です。
mark0はposition:absolute;です。ここでは示していませんが、absoluteでもoffsetParentは変化します。
mark1はposition:relative;です。offsetLeftが100でなく108なのは、body要素の左マージンのデフォルト値が8だからです。cssでbody{margin:0px;}とすれば100になります。
mark5と6のoffsetParentは要素parent1になります。要素parent1はposition:relative;です。直の親要素であるchild1(position指定なし)は対象になっていません。
mark7と8のoffsetParentは要素parent2になります。要素parent1はposition:absolute;です。直の親要素であるchild2(position指定なし)は対象になっていません。
以上から、offsetParentになる要素の条件は、以下があると考えられます。
- ノードツリー上方で、position:relative; position:absolute;となる直近の要素。
ここでは触れませんが、実際は更に以下のような条件が追加されます
- 対象要素がposition指定なしまたはstaticの場合、ノードツリー上方で直近の以下の要素
- タグ名が「table」「caption」「td」「th」の要素
(この他にも条件がありますが、複雑になるのでここでは省きます。現時点の調査結果は>>こちら<<にまとめています。
- 以上に該当がなければbody要素。
【参考サイト】 anything from hereHTML要素のサイズや位置を取得する offsetParentプロパティとは
offsetParentがbody要素で(position:absolute;以外の場合)、offsetLeft、offsetTopにはbody要素のmarginが加算されます。これにより、「ページ上の位置」になるわけです。ただし、border-widthは加算されません。当初、分かりやすいようにとbodyに枠線をつけていたのですが、逆に分かりにくくなるためコメントアウトしました。→2007/07/19追記。 FirefoxはBODYのborder-widthが加算されないどころか、減算されます。。。
Opera9
Operaを見てみます。
- 上記例の実行結果
id | offsetLeft | offsetTop | offsetParent |
---|---|---|---|
mark0 | 200 | 20 | body |
mark1 | 108 | 44 | body |
mark2 | 8 | 74 | body |
mark3 | 110 | 178 | body |
mark4 | 10 | 208 | body |
mark5 | 102 | 54 | parent1 |
mark6 | 2 | 84 | parent1 |
mark7 | 102 | 54 | parent2 |
mark8 | 2 | 84 | parent2 |
ほとんどNetscape等と変わりません。ただ、offsetLeftの値を見ると分かるのですが、+2されているケースが多いです。これはborderの2pxです。つまり、OperaはoffsetTop、offsetLeftの基準を要素の枠線内側*3でなく、枠線外側に置いていることになります。 この点は注意が必要です。
どっちがいいかは分からないですが。→累積することを考えると、含んでいるほうがありがたいです^^; 統一してほしいですね・・・。
offsetParentがbody要素で(position:absolute;以外)の場合、offsetLeft、offsetTopにはbody要素のmarginが加算されます。OperaのoffsetLeft、offsetTopはもともとborder-widthを含んでいるので、body要素に枠線があっても正しい値が取れます。
2006/12/12 追記。基準の枠線外/内問題。
これはDIV要素のケースで、Operaは枠線外側、Netscape、FireFoxと後述のIEでは枠線内側が基準になりますが、これがすべてのケース当てはまるわけではないということにさっき気が付きました><; Operaの例外はまだ見当たりませんが、Netscape、FireFox、IEに関して、今のところ以下の例外を見つけています。
たぶん、まだあると思います。おいおい調べていきます・・・。
枠線問題にも対応した座標算出関数を作成しようとしてて見つけたのですが。こうなるとちょっと大変・・・。だからprototype.jsは対応放棄してるのか・・・。
2007/01/22追記。この件に関してはこちらに調査結果をまとめています。
IE6
困ったチャンのIE。本家のくせに一番ややこしい><;
- 上記例の実行結果(Quirks mode)
id | offsetLeft | offsetTop | offsetParent |
---|---|---|---|
mark0 | 200 | 20 | body |
mark1 | 110 | 53 | body |
mark2 | 10 | 83 | body |
mark3 | 112 | 191 | body |
mark4 | 0 | 68 | child0 |
mark5 | 100 | 56 | parent1 |
mark6 | 0 | 68 | child1 |
mark7 | 100 | 56 | parent2 |
mark8 | 0 | 68 | child2 |
mark0〜3までは問題ないです(bodyのデフォルトマージンが違うくらい)。
問題はmark4。なぜかoffsetParentがchild0。。。
同じく、mark6のoffsetParentがchild1、mark7のoffsetParentがchild2、です・・・。
ここで実験。TESTボタンの横にあるチェックボックスのチェックを外してください。各要素child*の表示が変わります。それから再度TESTボタンを押してみましょう。すると・・・
- チェックボックスのチェックを外した場合(Quirks mode)
id | offsetLeft | offsetTop | offsetParent |
---|---|---|---|
mark0 | 200 | 20 | body |
mark1 | 110 | 53 | body |
mark2 | 10 | 83 | body |
mark3 | 112 | 191 | body |
mark4 | 0 | 86 | parent0 |
mark5 | 100 | 56 | parent1 |
mark6 | 0 | 86 | parent1 |
mark7 | 100 | 56 | parent2 |
mark8 | 0 | 86 | parent2 |
素直w→そうともいえませんね^^;(mark4とか)
何をしたかというと、各要素child*のwidth、height指定を外したのです。つまりIEには、offsetParentになる要素の条件について以下があるということです。
- 対象要素がposition指定なし(またはstatic)のとき、ノードツリー上方で直近のwidthもしくはheightが指定されている要素。
・・・訳がわからん><;
しかし、これでは終わりませんw 次に!DOCTYPE宣言を入れ替えて*4Standards modeにしてリロードし、もう一度TESTボタンを押してみてください。すると・・・
- 上記例の実行結果(Standards mode)
id | offsetLeft | offsetTop | offsetParent |
---|---|---|---|
mark0 | 200 | 20 | [HTML] |
mark1 | 110 | 53 | [HTML] |
mark2 | 0 | 68 | body |
mark3 | 112 | 191 | [HTML] |
mark4 | 0 | 68 | child0 |
mark5 | 100 | 56 | parent1 |
mark6 | 0 | 68 | child1 |
mark7 | 100 | 56 | parent2 |
mark8 | 0 | 68 | child2 |
ここで、[HTML]というのはHTML要素を意味しています*5。IEお得意(?)の「Standards modeではページ上のコンテンツはHTML要素上にあるとみなす」というやつです。・・・だったらなんでmark2のoffsetParentはbodyなのさ><;
つまり、
- IEのStandards modeでのoffsetParentは、通常body要素のところ、html要素になる。ただし、対象要素がposition無指定もしくはstaticである場合は除く(body要素がoffsetParent)。
・・・><;
いちおう。チェックを外すと。
- チェックボックスのチェックを外した場合(Standards mode)
id | offsetLeft | offsetTop | offsetParent |
---|---|---|---|
mark0 | 200 | 20 | [HTML] |
mark1 | 110 | 53 | [HTML] |
mark2 | 0 | 68 | body |
mark3 | 112 | 191 | [HTML] |
mark4 | 0 | 86 | parent0 |
mark5 | 100 | 56 | parent1 |
mark6 | 0 | 86 | parent1 |
mark7 | 100 | 56 | parent2 |
mark8 | 0 | 86 | parent2 |
この辺調査するのはとても疲れた・・・。
Quirks modeでoffsetParentがbody要素で(position:absolute;以外)の場合、offsetLeft、offsetTopにはbody要素のmarginが加算されます(border-widthは加算されない)。Standards modeではoffsetParentがbody要素の場合、marginは加算されません(div要素等と同じ扱い)。
【まとめ】
上記内容を踏まえ、更に>>下<<の詳細調査用サンプルから導き出した現時点の結論は以下です。。。
2007/01/22追記。例外があります。後述します。
対象要素のoffsetParentになる要素の条件
- ノードツリー上方で以下のいずれかとなる直近の要素。
- 以上に該当がなければbody要素。【IE】のStandards modeでは、html要素となる。ただし、対象要素がposition無指定もしくはstaticである場合は除く(body要素になる)。
闇はこれで終わらない。。。
とりあえずまとめてみましたが。これで網羅しているのかはちょっと分からず。。。
対応策としては以下があります。
【参考】 function cumulativeOffset(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return [valueL, valueT]; }
prototype.jsのPosition.cumulativeOffsetメソッドを関数にしただけですが^^; 要素を引数にして、offsetTopとoffsetLeftの累積を配列で返却してます(ただし、Opera以外では、各offsetParentに枠線があるとその分ずれが生じます・・・)。
2007/02/18追記。prototype.jsでの対策を以下に記述しました。
Positionオブジェクトの枠線幅問題対策 - Backstage of theater.js
テストしているうちに気づいたこととして、
- 親要素{position:relative; overflow:scroll; border:solid blue 2px;}
- 子要素{position:static;}
とすると子要素のoffsetLeftが「-2」(多分、枠線幅×-1)になる。
なんてのもありました。
闇が深すぎます・・・。撤退><;
2007/01/22追記。例外等の調査結果
撤退といいつつ、調査を続けていますが^^;
下の詳細調査用サンプルをよくよく調べてみたところ、「あれ?」というような現象をいくつか見つけたので追記します。上のまとめに追記すると更に訳が分からなくなるので、こちらに書きます。
- IE
- offsetParentがTABLE要素の場合、基準は枠線外側。
- Firefox
- offsetParentがTABLE, TH, TD要素の場合でposition:static;の場合、すべての要素について基準は枠線外側。
- position:relative;であるTD要素内の要素について
- position:absolute;の場合、offsetParentはBODY要素。
- position:relative;の場合、offsetParentはTD要素で基準は枠線内側。
- position:static;の場合、offsetParentはTD要素で基準は枠線外側。
- CAPTION要素内のposition:static;な要素のoffsetParentはTABLE要素となるが、offsetTop/Leftの値はBODY要素を基準にしている。
- Netscape
- offsetParentがTABLE, TH, TD要素の場合でposition:static;の場合、すべての要素について基準は枠線外側。
- position:relative;およびabsolute;であるTD要素内の要素について
- position:absolute;の場合、offsetParentはBODY要素。
- position:relative;の場合、offsetParentはTD要素で基準は枠線内側。
- position:static;の場合、offsetParentはTD要素で基準は枠線外側。
- CAPTION要素内のposition:static;な要素のoffsetParentはTABLE要素となるが、offsetTop/Leftの値はBODY要素を基準にしている。
・・・結論。TABLE要素内の要素のoffsetParent/Top/Leftは使用しないようにしよう><;
あと、position:absolute;でtop、left無指定時の表示位置が、ブラウザによってかなり異なることも分かりました。。pasition:absolute;時はtop、leftを指定するようにしましょう。(あたりまえか^^;)
FirefoxのBODY枠線問題
「http://hkom.blog1.fc2.com/blog-entry-503.html」を読ませていただいて知ったのですが、FirefoxでBODYに枠線があると、その分BODYのoffsetTop、offsetLeftから減算されるんですね・・・。調査の早い段階でBODYの枠線を外してしまっていたので、気が付きませんでした。あとで「Positionオブジェクトの枠線幅問題対策 - Backstage of theater.js」のほうも直しておきます。→直しました。
前述の枠線幅×-1になる件も、何か関連しているのかな・・・。
詳細調査用サンプル
2007/01/22改修。親要素の枠線を2px←→10pxに切り替えるチェックボックスを追加しました。また、いくつか要素を追加しています。
更に詳しく調べるためのサンプル。prototype.js使用です。
TESTボタンを押すと結果テーブルを表示します。テーブルの各idかoffsetParentのセルにマウスカーソルを合わせると、その要素の位置設定情報をツールチップで表示します。
resize childチェックボックスは背景色黄色の全要素のサイズ指定のon/offをします。position abs チェックボックスはposition:absolute;の要素の位置指定をon/offします(チェックを入れると、position:absolute;の要素が一部を除いて画面左上で重なります)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><!--Quirks mode--> <!--<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">--><!--Standards mode--> <html> <head> <title></title> <style> body{ /*Opera以外は入れると正しく取れなくなる・・・*/ /*border:solid blue 2px;*/ font-size:10px; letter-spacing:1px; } .mark{ background-color:red; width:30px; height:30px; } .rel{ position:relative; left:50px; top:20px; } .abs{ position:absolute; margin:10px; } .abs_p{ left:15px; top:20px; } .flt{ float:right; } #P-R{ left:150px; top:-10px; } #P-A{ left:200px; top:300px; } .parent{ border:solid blue 2px; width:120px; height:100px; } .child{ background-color:yellow; } .child_s{ width:100px; height:80px; } #table, #caption, #tr, #th, #td, #td-R, #td-A,#legend, #fieldset, #marquee, #map{ border:solid blue 2px; font-size:10px; letter-spacing:1px; } #view_t{ font-size:11px; letter-spacing:1px; background-color:lemonchiffon; } .border{ border:solid green 10px; } </style> <script language="javascript" src="prototype.js" charset="utf-8"></script> <script> function test(){ var ary = document.getElementsByClassName("target"); var str = "<table id='view_t' border><tr><th>id</th><th>offsetLeft</th>" + "<th>offsetTop</th><th>offsetParent</th></tr>"; str += ary.inject("", function(memo, value, index){ var op = value.offsetParent; var id = ""; if(op == document.body.parentNode){ id = "[HTML]" }else if(op){ id = op.id; } memo += "<tr><td"; memo += " title='position:" + Element.getStyle(value, 'position'); memo += "; left:" + Element.getStyle(value, 'left'); memo += "; top:" + Element.getStyle(value, 'top'); memo += "'>" + value.id + "</td>"; memo += "<td>" + value.offsetLeft + "</td>"; memo += "<td>" + value.offsetTop + "</td>"; memo += "<td"; if(op){ memo += " title='position:" + Element.getStyle(op, 'position'); memo += "; left:" + Element.getStyle(op, 'left'); memo += "; top:" + Element.getStyle(op, 'top'); } memo += "'>" + id + "</td></tr>"; return memo; }); str += "</table>"; Element.update('view', str); } function resize(obj){ var cary = document.getElementsByClassName("child"); var method = (obj.checked) ? 'addClassName' : 'removeClassName'; cary.each(function(value){Element[method](value, 'child_s');}); } function posabs(obj){ var aary = document.getElementsByClassName("abs"); var method = (obj.checked) ? 'addClassName' : 'removeClassName'; aary.each(function(value){Element[method](value, 'abs_p');}); } function swborder(obj){ var ary = document.getElementsByClassName("parent"); ary = ary.concat(['table', 'caption', /*'tr',*/ 'th', 'td', 'legend', /*'fieldset',*/ 'marquee', 'map', 'td-R', 'td-A'].collect(function(value){return $(value);})); var width = (obj.checked) ? '10px' : '2px'; ary.each(function(value){Element.setStyle(value, {'border-width':width});}); } </script> </head> <body id="body">body <div id="BC" class="child child_s">BC <div id="M-BA" class="target mark abs">M-BA</div> <div id="M-BR" class="target mark rel">M-BR</div> <div id="M-BS" class="target mark">M-BS</div> </div> <div id="P-S" class="parent">P-S <div id="SC" class="child child_s">SC <div id="M-SA" class="target mark abs">M-SA</div> <div id="M-SR" class="target mark rel">M-SR</div> <div id="M-SS" class="target mark">M-SS</div> </div> </div> <div id="P-R" class="parent rel">P-R <div id="RC" class="child child_s">RC <div id="M-RA" class="target mark abs">M-RA</div> <div id="M-RR" class="target mark rel">M-RR</div> <div id="M-RS" class="target mark">M-RS</div> </div> </div> <div id="P-A" class="parent abs">P-A <div id="AC" class="child child_s">AC <div id="M-AA" class="target mark abs">M-AA</div> <div id="M-AR" class="target mark rel">M-AR</div> <div id="M-AS" class="target mark">M-AS</div> </div> </div> <div id="P-Fl" class="parent flt">P-Fl <div id="FlC" class="child child_s">FlC <div id="M-FlA" class="target mark abs">M-FlA</div> <div id="M-FlR" class="target mark rel">M-FlR</div> <div id="M-FlS" class="target mark">M-FlS</div> </div> </div> <table id="table"> <caption id="caption">caption <div id="CpC" class="child child_s">CpC <div id="M-CpA" class="target mark abs">M-CpA</div> <div id="M-CpR" class="target mark rel">M-CpR</div> <div id="M-CpS" class="target mark">M-CpS</div> </div> </caption> <tr id="tr1" class="target"> <th id="th" class="target">th <div id="ThC" class="child child_s">ThC <div id="M-ThA" class="target mark abs">M-ThA</div> <div id="M-ThR" class="target mark rel">M-ThR</div> <div id="M-ThS" class="target mark">M-ThS</div> </div> </th> </tr> <tr id="tr2" class="target"> <td id="td" class="target">td <div id="TdC" class="child child_s">TdC <div id="M-TdA" class="target mark abs">M-TdA</div> <div id="M-TdR" class="target mark rel">M-TdR</div> <div id="M-TdS" class="target mark">M-TdS</div> </div> </td> </tr> <tr id="tr3" class="target"> <td id="td-R" class="target rel">td-R <div id="TdRC" class="child child_s">TdRC <div id="M-TdRA" class="target mark abs">M-TdRA</div> <div id="M-TdRR" class="target mark rel">M-TdRR</div> <div id="M-TdRS" class="target mark">M-TdRS</div> </div> </td> </tr> <tr id="tr4" class="target"> <td id="td-A" class="target abs">td-A <div id="TdAC" class="child child_s">TdAC <div id="M-TdAA" class="target mark abs">M-TdAA</div> <div id="M-TdAR" class="target mark rel">M-TdAR</div> <div id="M-TdAS" class="target mark">M-TdAS</div> </div> </td> </tr> </table> <div style="height:110px;"> </div> <fieldset id="fiedset"> <legend id="legend">legend <div id="LgC" class="child child_s">LgC <div id="M-LgA" class="target mark abs">M-LgA</div> <div id="M-LgR" class="target mark rel">M-LgR</div> <div id="M-LgS" class="target mark">M-LgS</div> </div> </legend> fieldset <div id="FsC" class="child child_s">FsC <div id="M-FsA" class="target mark abs">M-FsA</div> <div id="M-FsR" class="target mark rel">M-FsR</div> <div id="M-FsS" class="target mark">M-FsS</div> </div> </fieldset> <marquee id="marquee">marquee <div id="MqC" class="child child_s">MqC <div id="M-MqA" class="target mark abs">M-MqA</div> <div id="M-MqR" class="target mark rel">M-MqR</div> <div id="M-MqS" class="target mark">M-MqS</div> </div> </marquee> <map id="map">map <area id="area" class="target mark">area</area> </map> <div style="position:absolute;top:50px;left:400px;"> <button id="test" onclick="test();">TEST</button> <input type="checkbox" onclick="resize(this);" checked/>resize child <input type="checkbox" onclick="posabs(this);"/>position abs <input type="checkbox" onclick="swborder(this);"/>switch border <div id="view"></div> </div> </body> </html>