リンクアンカーの出力に関する諸問題

概要

レス内に記述された>>nといったリンクをクリックした場合、

documentObject.scrollTop=anchorObject[n].offsetTop;
anchorObject[n].scrollIntoView;

といった手法により画面をスクロールさせているが、この文章で問題とするのは、そのスクロール先となるanchorObjectの位置である。

現行の仕様とその問題点

現行の仕様

現行では、リンクアンカーは以下のように個々のレスの先頭に出力される。

<a name="*123"></a><dt><a href="menu:123">123</a><dt><font color="forestgreen">名無しさん・・・

現行の問題点

この仕様の場合、ブラウザでの動作では問題ないものの、Javascriptにおいて取り扱う場合に重要な問題が生じる。

概要

まず、Javascriptにおいては、outerHTMLというプロパティがあり、これによりオブジェクトをテキストとして取り出すことができる。

HTMLソース
<p>これがP要素の内容です。</p>
Javascript
var obj=document.getElementsByTagName("p")[0];
document.write(obj.outerHTML);
出力
<p>これがP要素の内容です。</p>

2ch用ブラウザでの適用

2ch用ブラウザで上記のことを行う場合、意図したものと異なる結果が生じることになる。

HTMLソース
<dl>
・・・(略)・・・
<a name="*122"></a><dt><a href="menu:122">122</a>・・(略)・・ <dd>これは122番目のレスの本文です。</dd>
<a name="*123"></a><dt><a href="menu:123">123</a>・・(略)・・ <dd>これは123番目のレスの本文です。</dd>
<a name="*124"></a><dt><a href="menu:124">124</a>・・(略)・・ <dd>これは124番目のレスの本文です。</dd>
Javascript
var obj=document.getElementsByTagName("DD")[122]; // 123番目のレスの本文を取得
document.write(obj.outerHTML);
期待される出力
<dd>これは123番目のレスの本文です。</dd>
実際の出力
<dd>これは123番目のレスの本文です。<a name="*124"></a></dd>

すなわち、次のリンクアンカーが一つ前の本文の中に存在してしまうものとして解釈されてしまうのである。

原因

2ch用ブラウザにより出力されるHTMLソースを階層構造であらわすと次のようになる。

<dl>

しかし、DLの直下の階層にはDTとDDしか存在しえないルールなので、IEは<a name="*123"></a>は、書き損じとみなしてしまう。

このIEの修正により、HTMLソースでは上記のようになっているにもかかわらず、メモリ上では次のように解釈をしているのである。

<dl>

上記のように、解釈されるため、HTMLソースとJavascriptによるメモリからの取得に齟齬が生じることになるのである。

TwiddleさんのBorland Delphi 6 Personal関連水平スクロールバーが出ている場合に水平スクロールもしてしまうというのは、これに起因しているような気もします。

(2003/07/04 追記)
これはscrollIntoView()が、厳密にオブジェクトの位置までスクロールするためである。通常BODY要素にpaddingがあるため、その分だけ横スクロールが生じるということである。
これを回避するには、IEコンポなら横スクロールが出ないようなCSSの設定をすることで回避できる。ただし、巨大AAは崩れて表示されてしまう諸刃の剣

また、元のHTMLに DOCTYPE宣言があると、上記のoffsetTop/scrollTop方式だとスクロールしないというのも、これに起因しているような気がします。

(2003/07/04 追記)
これはStrictのDOCTYPE宣言であるためである。
StrictのDOCTYPE宣言の場合、不適切な記述はすべて無視して解釈される。そのため、アンカーが消失してしまい対象レスにスクロールできなくなるのである。実際にTransitionalのDOCTYPE宣言では問題なくスクロールされる。

解法

リンクアンカーがずれてしまう問題については、次のようにリンクアンカーをメニューリンクの内部に出力することで解決することができる。

<dl>

改定仕様による影響

横スクロールの問題