これが答えですか?
「何かを計算する必要があるが表示しない場合は、要素をvisibility:hidden
andに設定しposition:absolute
、それを DOM ツリーに追加し、offsetHeight を取得して、削除します。(これは、プロトタイプ ライブラリが前回チェックした行の背後で行っていることです)。」
私は多くの要素で同じ問題を抱えています。このサイトで使用できる jQuery や Prototype はありませんが、機能する場合はテクニックを借りることに賛成です。うまくいかなかったものの例とそれに続くものとして、次のコードがあります。
// Layout Height Get
function fnElementHeightMaxGet(DoScroll, DoBase, elementPassed, elementHeightDefault)
{
var DoOffset = true;
if (!elementPassed) { return 0; }
if (!elementPassed.style) { return 0; }
var thisHeight = 0;
var heightBase = parseInt(elementPassed.style.height);
var heightOffset = parseInt(elementPassed.offsetHeight);
var heightScroll = parseInt(elementPassed.scrollHeight);
var heightClient = parseInt(elementPassed.clientHeight);
var heightNode = 0;
var heightRects = 0;
//
if (DoBase) {
if (heightBase > thisHeight) { thisHeight = heightBase; }
}
if (DoOffset) {
if (heightOffset > thisHeight) { thisHeight = heightOffset; }
}
if (DoScroll) {
if (heightScroll > thisHeight) { thisHeight = heightScroll; }
}
//
if (thisHeight == 0) { thisHeight = heightClient; }
//
if (thisHeight == 0) {
// Dom Add:
// all else failed so use the protype approach...
var elBodyTempContainer = document.getElementById('BodyTempContainer');
elBodyTempContainer.appendChild(elementPassed);
heightNode = elBodyTempContainer.childNodes[0].offsetHeight;
elBodyTempContainer.removeChild(elementPassed);
if (heightNode > thisHeight) { thisHeight = heightNode; }
//
// Bounding Rect:
// Or this approach...
var clientRects = elementPassed.getClientRects();
heightRects = clientRects.height;
if (heightRects > thisHeight) { thisHeight = heightRects; }
}
//
// Default height not appropriate here
// if (thisHeight == 0) { thisHeight = elementHeightDefault; }
if (thisHeight > 3000) {
// ERROR
thisHeight = 3000;
}
return thisHeight;
}
これは基本的に、ゼロの結果を得るためだけにあらゆることを試みます。影響のない ClientHeight。問題の要素では、通常、ベースで NaN を取得し、オフセットとスクロールの高さでゼロを取得します。次に、Add DOM ソリューションと clientRects を試して、ここで機能するかどうかを確認しました。
2011 年 6 月 29 日、実際にコードを更新して、DOM と clientHeight の両方に追加してみましたが、予想よりも良い結果が得られました。
1) clientHeight も 0 でした。
2) ドムは実際に私に素晴らしい身長を与えてくれました。
3) ClientRects は、DOM 手法とほぼ同じ結果を返します。
追加された要素は本質的に流動的であるため、それ以外の場合は空の DOM Temp 要素に追加されると、そのコンテナーの幅に従ってレンダリングされます。これは、最終的には 30 ピクセル短いため、奇妙になります。
高さの計算方法が異なることを示すために、いくつかのスナップショットを追加しました。

身長差が一目瞭然。確かに絶対配置と非表示を追加できますが、効果はないと確信しています。私はこれがうまくいかないと確信し続けました!
(さらに余談)実際のレンダリングの高さよりも高さが低く出ます(レンダリング)。これは、DOM Temp 要素の幅を既存の親と一致するように設定することで対処でき、理論的にはかなり正確に行うことができます。また、それらを削除して既存の場所に戻すとどうなるかわかりません。彼らは innerHTML テクニックを使って到着したので、私はこの別のアプローチを使用して探します。
* ただし *そのどれも必要ありませんでした。実際、宣伝どおりに機能し、正しい高さを返しました!!!
メニューを再び表示できるようになったとき、驚くべきことに DOM はページの上部 (279 ピクセル) の流動的なレイアウトごとに正しい高さを返しました。上記のコードでは、280px を返す getClientRects も使用しています。
これは、次のスナップショットに示されています (動作中の Chrome から取得)。

なぜそのプロトタイプのトリックが機能するのかはわかりませんが、機能するようです。または、getClientRects も機能します。
これらの特定の要素で発生した問題の原因は、appendChild の代わりに innerHTML を使用したことだと思いますが、それは現時点ではまったくの憶測です。