非表示要素の内側にあるdivのoffsetHeightを測定する必要があります。
<div id="parent" style="display: none;">
<div id="child">Lorem Ipsum dolor sit amet.</div>
</div>
親div mustは "display:none
"に設定する必要があります。私はそれを制御できません。子divのoffsetHeightが0になることに気づきました。回避策を見つける必要があります。
私がいじったのは、ページが読み込まれたときに、親の子ノードをコピーし、「visiblity:hidden
」に設定されているページのdivに挿入することです。次に、それらの要素の高さを測定し、完了したらノードを削除します。
他に何か考えはありますか?
更新:私がしなければならなかったことはこれでした:
YUI 2を使用して、ページの読み込み時に、display:noneに設定されているか、高さと幅が0であるその特定のクラス名のすべての要素を見つけました(これは、要素が存在するかどうか、または親が表示に設定されているかどうかを測定する1つの方法です) :なし)。次に、その要素をdisplay:blockに設定します。次に、その親について同じことを確認し、表示されている親が見つかるまで親を表示しました。最上位のdisplay:none祖先がdisplay:blockに設定されると、要素を測定できます。
すべての要素が測定されたら、すべての要素をdisplay:noneにリセットします。
要素の寸法を取得している間、非常に短い間、要素の親を表示にする必要があります。一般的なソリューションでは、すべての祖先が通常トラバースされ、表示されます。次に、それらのdisplay
値を元の値に戻します。
もちろん、パフォーマンスの問題があります。
Prototype.jsの実装ではこのアプローチを検討しましたが、最終的にはgetWidth
およびgetHeight
実際の要素のみを表示となり、祖先をたどることはありませんでした。
「非表示」の親から要素を削除するなど、代替ソリューションの問題は、「通常の」階層から外れると、特定のスタイルが要素に適用されなくなる可能性があることです。次のような構造がある場合:
<div class="foo" style="display:none;">
<div class="bar">...</div>
</div>
そしてこれらのルール:
.bar { width: 10em; }
.foo .bar { width: 15em; }
次に、要素をその親から取り出すと、実際には間違った寸法になります。
要素のクローンを作成し、絶対に-10000、-10000に配置し、クローンを測定して破棄することができます。
style.display = "none"
を使用すると、要素の幅と高さが0になります。
ただし、代わりにstyle.visibility = "hidden"
を使用すると、要素は(通常どおり)ブラウザによって計算された幅と高さを持ちます。
Jqueryを使用せず、クローンも作成しない純粋なjsソリューションを作成しました(これはより高速だと思います)。
var getHeight = function(el) {
var el_style = window.getComputedStyle(el),
el_display = el_style.display,
el_position = el_style.position,
el_visibility = el_style.visibility,
el_max_height = el_style.maxHeight.replace('px', '').replace('%', ''),
wanted_height = 0;
// if its not hidden we just return normal height
if(el_display !== 'none' && el_max_height !== '0') {
return el.offsetHeight;
}
// the element is hidden so:
// making the el block so we can meassure its height but still be hidden
el.style.position = 'absolute';
el.style.visibility = 'hidden';
el.style.display = 'block';
wanted_height = el.offsetHeight;
// reverting to the original values
el.style.display = el_display;
el.style.position = el_position;
el.style.visibility = el_visibility;
return wanted_height;
}
これがデモです https://jsfiddle.net/xuumzf9k/1/
これに改善点が見つかれば、私に知らせてください(私の主なプロジェクトでこれを使用しています)
したがって、ここでは、lod3nの回答と999のコメントに基づいて動作するjQueryソリューションを示します。
var getHiddenElementHeight = function(element){ var tempId = 'tmp-' + Math.floor(Math.random()* 99999); //念のために一意のIDを生成する $(element).clone() .css( 'position'、 'absolute') .css( 'height'、 'auto')。css( 'width'、 ' 1000px ') //親要素に直接挿入して、すべてのCSSが適用されるようにします(はい、わかっています。:first-childと他の擬似的なものは除きます。 .appendTo($(element) .parent()) .css( 'left'、 '-10000em') .addClass(tempId).show() h = $( '。' + tempId ).height() $( '。' + tempId).remove() return h; }
楽しい!
回避策は、height
を0
に設定することです
.hidden {
height:0;
overflow: hidden;
}
次に、要素scrollHeight
を取得します。
document.querySelector('.hidden').scrollHeight
要素は表示されませんが、scrollHeightは正しく高さを提供します。要素の流れにも影響はないと思います。
Z-indexを使用して、不透明な要素の下にある要素を非表示にし、表示して、高さを取得します。
したがって、display:none;
からheight:0; overflow:hidden;
?多分あなたはあなた自身のスタイルシートでそれを上書きすることができます:
div#parent { display: block !important; height:0; overflow:hidden; }
そして、YUIを使用している場合(YUI 2を想定)、これを使用できます。
var region = YAHOO.util.Dom.getRegion('child');
子の寸法とオフセットを取得します。
要素がレンダリングされるまで、高さはありません。親オブジェクトを複製して、ユーザーから見えない場所に表示しても、複製の高さが非表示オブジェクトの最終サイズと同じになるとは限りません。
必ずしもクローンでレンダリングされるとは限らない高さに影響を与える可能性のある多くのものがあります-DOM内のあらゆるものとCSSルールとの相互作用により、DOMの他の要素のレンダリングに変更が生じる可能性があります。ドキュメント全体のクローンを作成しないと(それが完全に保証されていない場合でも)、非表示オブジェクトの高さを決定する方法はありません。
mustがユーザーに表示される前に高さがわかっている場合は、できるだけ短い時間表示してからもう一度非表示にして、「ハッキング」する必要があります。ほとんどの場合、ユーザーにはこの問題が発生し、結果に満足できません。
使用してみてください:
#parent{ display:block !important; visibility:hidden; position:absolute}
ヘルパー関数---
function getElementHeight(el) {
var clone = el.cloneNode(true);
var width = el.getBoundingClientRect().width;
clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset; width: ' + width + 'px';
document.body.append(clone);
var height = clone.getBoundingClientRect().height + 'px';
clone.remove();
return height;
}
クローンを作成し、それをDOM(非表示)に追加し、高さを取得してから削除します。
fixed
とtop
/left
の位置は、アプリが本体レベルでのスクロールを許可している場合に備えています-スクロールバーレイブパーティーを防止しようとします-処理すると削除できます子要素をスクロールします。
Overflow
、height
、max-height
設定を使用して高さ設定を「リセット」しようとし、クローンの自然な高さになります。
Visibility
の場合、明白なポインタイベントの場合は、「念のため」、要素のレンダリングに時間がかかり、ユーザー入力を中断したくない場合。
動的な高さを可能にする「アコーディオンのような」アニメーション化された開閉の例.
function getElementHeight(el) {
var clone = el.cloneNode(true);
clone.style.cssText = 'position: fixed; top: 0; left: 0; overflow: auto; visibility: hidden; pointer-events: none; height: unset; max-height: unset';
document.body.append(clone);
var height = clone.getBoundingClientRect().height + 'px';
clone.remove();
return height;
}
var expanded = false;
function toggle() {
var el = document.getElementById('example');
expanded = !expanded;
if (expanded) {
el.style.maxHeight = getElementHeight(el);
// Remove max-height setting to allow dynamic height after it's shown
setTimeout(function() {
el.style.maxHeight = 'unset';
}, 1000); // Match transition
} else {
// Set max height to current height for something to animate from
el.style.maxHeight = getElementHeight(el);
// Let DOM element update max-height, then set to 0 for animated close
setTimeout(function() {
el.style.maxHeight = 0;
}, 1);
}
}
#example {
overflow: hidden;
max-height: 0;
transition: max-height 1s;
}
<button onclick="toggle()">Toggle</button>
<div id="example">
<textarea>Resize me</textarea>
</div>
私がしなければならなかったことはこれでした:
YUI 2を使用して、ページの読み込み時に、display:noneに設定されているか、高さと幅が0である、指定されたクラス名のすべての要素を見つけました(要素が存在するかどうか、または親が表示に設定されているかどうかを測定する1つの方法です) :なし)。次に、その要素をdisplay:blockに設定します。次に、同じことについて親であることを確認し、表示されている親が見つかるまで親を表示しました。最上位のdisplay:none祖先がdisplay:blockに設定されると、要素を測定できます。
すべての要素が測定されたら、すべての要素をdisplay:noneにリセットします。