web-dev-qa-db-ja.com

非表示要素の「潜在的な」幅を見つける

現在、ドロップダウンメニューで機能するように lavalampプラグイン を拡張していますが、小さな問題が発生しました。非表示になっている要素のoffsetWidthを知る必要があります。明らかに、この質問は意味がありません。むしろ、私が探しているのは、それが隠されていない場合の要素のoffsetWidthです。

解決策はそれを表示し、幅をつかんで、もう一度非表示にすることですか?より良い方法があるはずです...

32
Gausie

私が考えられる唯一のことは、offsetWidthを取得できるようにそれ(またはそのクローン)を表示することです。

この測定ステップでは、その位置を絶対値にし、xまたはyの値を大きな負の値にして、レンダリングされますがユーザーには見えないようにします。

37
Peter Bailey

CSS _visibility: hidden_を持つ要素の幅は測定可能です。 _display: none_の場合にのみ、まったくレンダリングされません。したがって、要素が絶対配置されることが確実である場合(表示時にレイアウトが変更されないようにするため)、css('visibility', 'hidden')の代わりにhide()を使用して要素を非表示にします。幅を測定しても問題ありません。

それ以外の場合は、はい、show-measure-hideは機能します。

36
bobince

次の関数を使用して、要素の外側の幅非表示のコンテナ内を取得できます。

_$.fn.getHiddenOffsetWidth = function () {
    // save a reference to a cloned element that can be measured
    var $hiddenElement = $(this).clone().appendTo('body');

    // calculate the width of the clone
    var width = $hiddenElement.outerWidth();

    // remove the clone from the DOM
    $hiddenElement.remove();

    return width;
};
_

状況に応じて.outerWidth().offsetWidth()に変更できます。

この関数は最初に要素を複製し、表示される場所にコピーします。次に、オフセット幅を取得し、最後にクローンを削除します。次のスニペットは、この関数が完璧になる状況を示しています。

_<style>
    .container-inner {
        display: none;
    }

    .measure-me {
        width: 120px;
    }
</style>

<div class="container-outer">
    <div class="container-inner">
        <div class="measure-me"></div>
    </div>
</div>
_

要素の幅を変更するCSSが要素に適用されていて、ボディの直接の子孫の場合は適用されない場合、このメソッドは機能しないことに注意してください。したがって、このようなものは、関数が機能しないことを意味します:

_.container-outer .measure-me {
    width: 100px;
}
_

次のいずれかを行う必要があります。

  • つまり、CSSセレクターの特異性を変更します。 _.measure-me { width: 100px; }_
  • appendTo()を変更して、CSSもクローンに適用される場所にクローンを追加します。どこに配置しても、要素が表示されることを確認してください:.appendTo('.container-outer')

繰り返しますが、この関数は、要素が非表示のコンテナー内にあるため、要素が非表示になっていると想定しています。要素自体が_display:none_の場合、オフセット幅を取得する前に、コードを追加してクローンを表示することができます。このようなもの:

_$.fn.getHiddenOffsetWidth = function () {
    var hiddenElement $(this)
        width = 0;

    // make the element measurable
    hiddenElement.show();

    // calculate the width of the element
    width = hiddenElement.outerWidth();

    // hide the element again
    hiddenElement.hide();

    return width;
}
_

これは、次のような状況で機能します。

_<style>
    .measure-me {
        display: none;
        width: 120px;
    }
</style>

<div class="container">
    <div class="measure-me"></div>
</div>
_
12
ajbeaven

2つのオプション:

  1. 要素をビューポートの外に配置します(例:_left:-10000px_)
  2. hide()の代わりに_visibility: hidden_または_opacity: 0_を使用します。

どちらの方法でも、要素を非表示にすることで機能しますが、計算された幅を取得できます。 Safariをこのように使用する場合は注意してください。非常に高速で、場合によっては速すぎます...

2
David Hellsing

実際のjQueryプラグイン

用途:

console.log('width without actual: ' + $('#hidden').width());

console.log('width with actual: ' + $('#hidden').actual('width'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.actual/1.0.19/jquery.actual.min.js"></script>

<div style="width: 100px; display: none;">
  <div id="hidden"></div>
</div>

私がしたことはその要素を非表示にするまでに、その幅をデータセットに格納しました。 プログラムで非表示にできる場合にのみ機能します。

すなわち。

非表示の場合;

var elem = $("selectorOfElement");

elem.dataset.orgWidth = elem.clientWidth;

後で取得する;

var elem = $("selectorOfElement");

var originalWidthWas = elem.dataset.orgWidth;
1
Aykut Yararbas

要素が親要素の全幅であることを知っている場合、別のアプローチは再帰的メソッドを作成することです:

es5:

var getWidth;
getWidth = function($el){
  return $el.offsetWidth || getWidth($el.parentElement);
}
var width = getWidth(document.getElementById('the-element'));

es6:

let getWidth
getWidth = ($el) => $el.offsetWidth || getWidth($el.parentElement)

const width = getWidth(document.getElementById('the-element'))
1
Gustaf Eriksson

ディスプレイで非表示になっているためです。過去に行われたことは、ページからそれを取得するために絶対配置を使用する「レシーバー」divを作成することです。次に、そこに新しい要素をロードし、寸法を取得して、完了したら削除します。完了したらレシーバーを削除します。

あなたができる別のことは、hide()を使用しないことです。しかし、代わりに可視性を設定するには:非表示。表示:;ただし、これは、ノードが接続されている場所に空白の領域がレンダリングされることを意味します。

0
prodigitalson

私は隠し要素の機能を見つけようとしましたが、CSSは誰もが考えるよりもはるかに複雑であることに気づきました。 CSS3には、フレキシブルボックス、グリッド、列、複雑な親要素内の要素など、以前のすべての回答では機能しない可能性のある新しいレイアウトテクニックがたくさんあります。

フレキシボックスの例 enter image description here

持続可能でシンプルな解決策はリアルタイムレンダリングだけだと思います。その時、ブラウザはあなたに正しい要素サイズを与えるはずです。

悲しいことに、JavaScriptは要素が表示または非表示になったときに通知する直接イベントを提供しません。ただし、要素の可視性が変更されたときにコールバック関数を実行するDOM属性変更APIに基づいていくつかの関数を作成します。

$('[selector]').onVisibleChanged(function(e, isVisible)
{
    var realWidth = $('[selector]').width();
    var realHeight = $('[selector]').height();

    // render or adjust something
});

詳細については、私のプロジェクトGitHubにアクセスしてください。

https://github.com/Soul-Master/visible.event.js

デモ: http://jsbin.com/ETiGIre/7

0
Soul_Master