非表示のdiv内にある要素の高さを取得する必要があります。現在、divを表示し、高さを取得し、親divを非表示にします。これは少しばかげているようです。もっと良い方法はありますか?
私はjQuery 1.4.2を使用しています:
$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
非表示のdiv内にある要素の高さを取得する必要があります。現在、divを表示し、高さを取得し、親divを非表示にします。これは少しばかげているようです。もっと良い方法はありますか?
私はjQuery 1.4.2を使用しています:
$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
回答:
あなたはこのようなことをすることができますが、少しハッキーですが、position
すでに絶対的であるかどうか忘れてください:
var previousCss = $("#myDiv").attr("style");
$("#myDiv").css({
position: 'absolute', // Optional if #myDiv is already absolute
visibility: 'hidden',
display: 'block'
});
optionHeight = $("#myDiv").height();
$("#myDiv").attr("style", previousCss ? previousCss : "");
position:relative
場合は、もちろんの代わりにそれを設定する必要がありstatic
ます。
隠し要素の幅を取得する際に同じ問題に遭遇したので、このプラグインを修正するためにjQuery Actualを呼び出すこのプラグインを書きました。使用する代わりに
$('#some-element').height();
使用する
$('#some-element').actual('height');
非表示の要素に適切な値を与えるか、要素に非表示の親があります。
この助けを願っています:)
表示スタイルと表示スタイルという2つのCSSスタイルを混乱させています。
可視性のcssスタイルを設定して要素を非表示にした場合、要素がページ上でスペースを取るため、要素が表示されているかどうかに関係なく高さを取得できるはずです。
要素が表示cssスタイルを「なし」に変更することによって非表示になっている場合、要素はページ上のスペースを取らないので、要素をあるスペースにレンダリングする表示スタイルを指定する必要があります。どのポイント、あなたは高さを得ることができます。
visibility
しhidden
ても問題は解決しませんでしたが、設定するというアイデアが得られposition: fixed; top: 100%
、魅力のように機能しました!
私は時々これに対処するために少しの策略に実際に頼りました。スクロール可能なコンテンツが非表示のマークアップの一部であるかどうか、事前にわからない問題が発生したjQueryスクロールバーウィジェットを開発しました。これが私がしたことです:
// try to grab the height of the elem
if (this.element.height() > 0) {
var scroller_height = this.element.height();
var scroller_width = this.element.width();
// if height is zero, then we're dealing with a hidden element
} else {
var copied_elem = this.element.clone()
.attr("id", false)
.css({visibility:"hidden", display:"block",
position:"absolute"});
$("body").append(copied_elem);
var scroller_height = copied_elem.height();
var scroller_width = copied_elem.width();
copied_elem.remove();
}
これはほとんどの部分で機能しますが、発生する可能性のある明らかな問題があります。複製するコンテンツがルールに親マークアップへの参照を含むCSSでスタイル設定されている場合、複製されたコンテンツには適切なスタイルが含まれず、測定値がわずかに異なる可能性があります。これを回避するには、複製するマークアップに、親マークアップへの参照を含まないCSSルールが適用されていることを確認します。
また、これは私のスクローラーウィジェットでは思い付きませんでしたが、複製された要素の適切な高さを取得するには、幅を親要素と同じ幅に設定する必要があります。私の場合、CSS幅は常に実際の要素に適用されていたので、これについて心配する必要はありませんでしたが、要素に幅が適用されていない場合は、何らかの再帰的な処理が必要になる場合があります要素のDOM祖先をたどって、適切な親要素の幅を見つけます。
JSBinでのユーザーNickの回答とユーザーhitautodestructのプラグインにさらに基づいて、幅と高さの両方を取得し、これらの値を含むオブジェクトを返す同様のjQueryプラグインを作成しました。
ここで見つけることができます:http :
//jsbin.com/ikogez/3/
以前のバージョン(上記)は、多くのDOM操作が行われている実際の環境では実際には使用できないことが判明したため、この小さな小さなプラグインを完全に再設計しました。
これは完全に機能しています:
/**
* getSize plugin
* This plugin can be used to get the width and height from hidden elements in the DOM.
* It can be used on a jQuery element and will retun an object containing the width
* and height of that element.
*
* Discussed at StackOverflow:
* http://stackoverflow.com/a/8839261/1146033
*
* @author Robin van Baalen <robin@neverwoods.com>
* @version 1.1
*
* CHANGELOG
* 1.0 - Initial release
* 1.1 - Completely revamped internal logic to be compatible with javascript-intense environments
*
* @return {object} The returned object is a native javascript object
* (not jQuery, and therefore not chainable!!) that
* contains the width and height of the given element.
*/
$.fn.getSize = function() {
var $wrap = $("<div />").appendTo($("body"));
$wrap.css({
"position": "absolute !important",
"visibility": "hidden !important",
"display": "block !important"
});
$clone = $(this).clone().appendTo($wrap);
sizes = {
"width": $clone.width(),
"height": $clone.height()
};
$wrap.remove();
return sizes;
};
sizes = {"width": $wrap.width(), "height": $wrap.height()};
のthis
参照が必要です。
$wrap
(少なくとも私のテストでは)をターゲットにすることも可能です。私は試してみましたがthis
、this
まだ隠された要素を参照しているため、サイズをキャッチしません。
ニックの答えにさらに基づいて:
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").css({'position':'static','visibility':'visible', 'display':'none'});
私はこれを行う方が良いことがわかりました:
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").removeAttr('style');
CSS属性を設定するとインラインで挿入され、CSSファイルにある他の属性が上書きされます。HTML要素のスタイル属性を削除すると、最初は非表示だったので、すべてが通常に戻り、非表示になります。
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'}); optionHeight = $("#myDiv").height(); $("#myDiv").css({'position':'','visibility':'', 'display':''});
私は隠し要素の機能を見つけようとしましたが、CSSは誰もが考えるよりもはるかに複雑であることに気づきました。CSS3には、フレキシブルボックス、グリッド、列、複雑な親要素内の要素など、以前のすべての回答では機能しない可能性のある新しいレイアウトテクニックがたくさんあります。
flexiboxの例
持続可能でシンプルなソリューションは、リアルタイムレンダリングだけだと思います。その時、ブラウザはあなたにその正しい要素サイズを与えるはずです。
悲しいことに、JavaScriptは要素が表示または非表示になったときに通知する直接イベントを提供しません。ただし、要素の可視性が変更されたときにコールバック関数を実行するDOM属性変更APIに基づいていくつかの関数を作成します。
$('[selector]').onVisibleChanged(function(e, isVisible)
{
var realWidth = $('[selector]').width();
var realHeight = $('[selector]').height();
// render or adjust something
});
詳細については、私のプロジェクトGitHubにアクセスしてください。
style
属性の変更によって引き起こされる可視性の変更のみをチェックすることに注意してください(ここで 59行目を参照)。可視性の変更はclass
属性の変更によっても引き起こされる可能性があります。
Nick Craverのソリューションに従って、要素の可視性を設定すると、要素の正確な寸法を取得できます。私はこのソリューションを非常に頻繁に使用しました。ただし、スタイルを手動でリセットする必要があるため、開発のcssで要素の初期配置/表示を変更すると、関連するJavaScriptコードを更新するのを忘れることが多いため、これが面倒なことに気付きました。次のコードは、スタイルごとのスタイルをリセットしませんが、JavaScriptによって追加されたインラインスタイルを削除します。
$("#myDiv")
.css({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
optionHeight = $("#myDiv").height();
optionWidth = $("#myDiv").width();
$("#myDiv").attr('style', '');
ここでの唯一の前提は、他のインラインスタイルはあり得ないということです。そうしないと、それらも削除されます。ただし、ここでの利点は、要素のスタイルがcssスタイルシートにあったものに戻されることです。結果として、これは、要素が渡され、高さまたは幅が返される関数として記述できます。
jsを介してインラインでスタイルを設定する際に私が見つけたもう1つの問題は、css3を介して遷移を処理するときに、スタイルルールの重みをインラインスタイルよりも強くするように強制されるため、苛立たしい場合があります。
定義上、要素は表示されている場合にのみ高さを持ちます。
気になるところ:なぜ隠し要素の高さが必要なのですか?
1つの代替方法は、何らかの要素のオーバーレイを(z-indexを使用して)後ろに置くことで、要素を効果的に非表示にすることです。
私の状況では、高さの値を取得できないようにする隠し要素もありましたが、それは要素自体ではなく、親の1つだったので、プラグインの1つをチェックして、それが非表示の場合は、最も近い非表示要素を検索します。次に例を示します。
var $content = $('.content'),
contentHeight = $content.height(),
contentWidth = $content.width(),
$closestHidden,
styleAttrValue,
limit = 20; //failsafe
if (!contentHeight) {
$closestHidden = $content;
//if the main element itself isn't hidden then roll through the parents
if ($closestHidden.css('display') !== 'none') {
while ($closestHidden.css('display') !== 'none' && $closestHidden.size() && limit) {
$closestHidden = $closestHidden.parent().closest(':hidden');
limit--;
}
}
styleAttrValue = $closestHidden.attr('style');
$closestHidden.css({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
contentHeight = $content.height();
contentWidth = $content.width();
if (styleAttrValue) {
$closestHidden.attr('style',styleAttrValue);
} else {
$closestHidden.removeAttr('style');
}
}
実際、これはニック、グレゴリー、まぶたの反応の融合であり、グレゴリーの改善された方法を使用できますが、スタイル属性に戻す必要があるものがあると思われる場合は両方の方法を利用して探します親要素。
私の解決策の私の唯一の不満は、親を通るループが完全に効率的ではないということです。
1つの回避策は、高さを取得する要素の外側に親divを作成し、高さを「0」に適用して、オーバーフローを非表示にすることです。次に、子要素の高さを取得し、親のオーバーフロープロパティを削除します。
var height = $("#child").height();
// Do something here
$("#parent").append(height).removeClass("overflow-y-hidden");
.overflow-y-hidden {
height: 0px;
overflow-y: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent" class="overflow-y-hidden">
<div id="child">
This is some content I would like to get the height of!
</div>
</div>
これは、非表示の要素のjQueryのすべてのディメンションメソッドを処理するために作成したスクリプトです(非表示の親の子孫も含みます)。もちろん、これを使用するとパフォーマンスが低下することに注意してください。
// Correctly calculate dimensions of hidden elements
(function($) {
var originals = {},
keys = [
'width',
'height',
'innerWidth',
'innerHeight',
'outerWidth',
'outerHeight',
'offset',
'scrollTop',
'scrollLeft'
],
isVisible = function(el) {
el = $(el);
el.data('hidden', []);
var visible = true,
parents = el.parents(),
hiddenData = el.data('hidden');
if(!el.is(':visible')) {
visible = false;
hiddenData[hiddenData.length] = el;
}
parents.each(function(i, parent) {
parent = $(parent);
if(!parent.is(':visible')) {
visible = false;
hiddenData[hiddenData.length] = parent;
}
});
return visible;
};
$.each(keys, function(i, dimension) {
originals[dimension] = $.fn[dimension];
$.fn[dimension] = function(size) {
var el = $(this[0]);
if(
(
size !== undefined &&
!(
(dimension == 'outerHeight' ||
dimension == 'outerWidth') &&
(size === true || size === false)
)
) ||
isVisible(el)
) {
return originals[dimension].call(this, size);
}
var hiddenData = el.data('hidden'),
topHidden = hiddenData[hiddenData.length - 1],
topHiddenClone = topHidden.clone(true),
topHiddenDescendants = topHidden.find('*').andSelf(),
topHiddenCloneDescendants = topHiddenClone.find('*').andSelf(),
elIndex = topHiddenDescendants.index(el[0]),
clone = topHiddenCloneDescendants[elIndex],
ret;
$.each(hiddenData, function(i, hidden) {
var index = topHiddenDescendants.index(hidden);
$(topHiddenCloneDescendants[index]).show();
});
topHidden.before(topHiddenClone);
if(dimension == 'outerHeight' || dimension == 'outerWidth') {
ret = $(clone)[dimension](size ? true : false);
} else {
ret = $(clone)[dimension]();
}
topHiddenClone.remove();
return ret;
};
});
})(jQuery);
以前にページに要素をすでに表示している場合は、要素が非表示の場合でも設定されるため、DOM要素から直接高さを取得できます(jQueryで.get(0)を使用して到達可能)。
$('.hidden-element').get(0).height;
幅も同じ:
$('.hidden-element').get(0).width;
(修正のためにSkeets O'Reillyに感謝)
undefined
display='none'
、これは機能しません。