jQuery: jQuery'de gizli öğenin yüksekliğini al


249

Gizli bir div içindeki bir öğenin yüksekliğini almam gerekiyor. Şu anda div'ı gösteriyorum, yüksekliği elde ediyorum ve üst div'ı gizliyorum. Bu biraz aptalca görünüyor. Daha iyi bir yol var mı?

JQuery 1.4.2 kullanıyorum:

$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();

42
+1 Örnek çözümünüz lol cevaplarından daha iyidir.
Tim Santeford

9
Tim'e katılmıyorum. Bu çözümle, aslında öğeyi gösterip gizlediğiniz için ekranın titremesi ihtimali vardır. Nicks çözümü daha kıvrımlı olmasına rağmen, ana div asla gösterilmediği için ekranı titretme şansı yoktur.
Humphrey



5
Harry, aslında öğrendiğiniz şey, kodunuzun bu çözümde değil IE'de çalışmadığı. Kodunuzu ayıklayın :)
Gavin

Yanıtlar:


181

Böyle bir şey yapabilirsin, ama biraz acayip, positionzaten mutlak olup olmadığını unutma :

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 : "");

17
Yukarıdaki kodu jsbin.com/ihakid/2 jQ eklentisine birleştirdim . Bir sınıf da kullanıyorum ve ebeveynlerin de gizli olup olmadığını kontrol ediyorum.
hitautodestruct

3
+1 Bu harika çalışıyor. Sadece öğenin ebeveynlerinin de görüntülenmesi gerektiğini unutmayın. Bu beni birkaç dakika karıştırdı. Ayrıca, öğe ise position:relative, elbette bunun yerine bunu ayarlamak isteyeceksiniz static.
Michael Mior

6
Bu yöntemi kullandığınızda, hedef öğe genellikle şekli değiştirebilir. Bu nedenle, div'ın kesinlikle konumlandırıldığında yüksekliğini ve / veya genişliğini elde etmek çok yararlı olmayabilir.
Jeremy Ricketts

2
@Gavin, bu yeniden akış hesaplamasını ve kullanıcının titremesini önler, böylece hem daha ucuz hem de daha az müdahaleci olur.
Nick Craver

2
@hitautodestruct, yalnızca eklentinin gerçekten gizli olduğunu kontrol etmek için sorgu eklentinizi değiştirdim. jsbin.com/ihakid/58
Prasad

96

Gizli eleman genişliği alma ile aynı sorunla karşılaştım, bu yüzden bu eklentiyi düzeltmek için jQuery Actual çağrısı yazdım . Kullanmak yerine

$('#some-element').height();

kullanım

$('#some-element').actual('height');

gizli öğe için doğru değeri verir veya öğe gizli bir üst öğeye sahiptir.

Tam dokümantasyon için lütfen buraya bakınız . Ayrıca sayfada bir demo yer alıyor.

Umarım bu yardım :)


3
Evet yardımcı olur! 2015 ve hala yardımcı oluyor. Gerçek web sitesinde "jquery eski sürümleri" diyorsunuz - ancak - v2.1.3 hala gerekli, en azından benim durumumda oldu.
LpLrich

Teşekkürler! Bu eklentiyi başlangıçta akordeonlar içinde gizlenmiş öğelerin yüksekliğini (bu dinamik olarak yapılır) okumak ve ayarlamak için kullandım
alds

Harika bir eklenti! % 100'e ayarlandığında modalın içindeki bir div genişliğini elde etmek için her şeyi denedim ve hiçbir şey işe yaramadı. 5 saniye içinde kurmak ve mükemmel çalıştı!
Craig Howell

@ben Bağlantı koptu.
Sachin Prasad

39

İki CSS stili, ekran stili ve görünürlük stili oluşturuyorsunuz .

Görünürlük css stilini ayarlayarak öğe gizlenmişse, öğe sayfada hala yer kapladığı için öğenin görünür olup olmadığına bakılmaksızın yüksekliği elde edebilmeniz gerekir .

Öğe, görüntü css stilini "none" olarak değiştirerek gizlenmişse, öğe sayfada yer kaplamaz ve öğeye bir alanda görüntülenmesine neden olacak bir görüntüleme stili vermeniz gerekir. hangi noktada, yüksekliği elde edebilirsiniz.


Bunun için teşekkürler. benim sorunum bir tablo hücresini katılan ve ayar visibilityiçin hiddensorunumu çözmedi ama sete bana fikir verdi position: fixed; top: 100%ve bir cazibe gibi çalışır!
Jayen

Şimdi yüksekliğinin neden ekranla gösterilmediğini anlıyorum: hiçbir öğe yok. Harika açıklama için çok teşekkürler.
FrenkyB

30

Aslında zaman zaman bununla başa çıkmak için biraz hileye başvurdum. Kaydırılabilir içerik, işaretlemenin gizli bir parçasının bir parçası olup olmadığı konusunda önceden bilmediğim bir sorunla karşılaştığım bir jQuery kaydırma çubuğu widget'ı geliştirdim. İşte yaptım:

// 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();
}

Bu çoğunlukla işe yarıyor, ancak potansiyel olarak ortaya çıkabilecek belirgin bir sorun var. Klonladığınız içerik, kurallarında üst işaretlemeye referanslar içeren CSS ile stilize edilmişse, klonlanmış içerik uygun stili içermez ve muhtemelen biraz farklı ölçümlere sahip olur. Bu sorunu aşmak için, klonladığınız biçimlendirmede üst biçimlendirmeye referans içermeyen CSS kurallarının uygulandığından emin olabilirsiniz.

Ayrıca, bu benim kaydırma aracımla gelmedi, ancak klonlanan öğenin uygun yüksekliğini elde etmek için genişliği ana öğenin aynı genişliğine ayarlamanız gerekir. Benim durumumda, bir CSS genişliği her zaman gerçek öğeye uygulandı, bu yüzden bunun için endişelenmem gerekmiyordu, ancak öğenin üzerine bir genişlik uygulanmadıysa, bir tür özyinelemeli yapmanız gerekebilir. uygun üst öğenin genişliğini bulmak için öğenin DOM ailesinin çapraz geçişi.


Bu ilginç bir sorun var. Öğe zaten bir blok öğesiyse, klon, bir kap içindeki boyutundan farklı olan tüm vücut genişliğini (gövde dolgusu veya kenar boşluğu hariç) alacaktır.
Meligy

16

Kullanıcı Nick'in yanıtı ve JSBin kullanıcı hitautodestruct eklentisi üzerine daha fazla bina, hem genişlik hem de yüksekliği alıp bu değerleri içeren bir nesne döndüren benzer bir jQuery eklentisi oluşturdum.

Burada bulunabilir: http://jsbin.com/ikogez/3/

Güncelleme

Bu küçük küçük eklentiyi tamamen yeniden tasarladım, çünkü önceki sürümün (yukarıda belirtilen) çok fazla DOM manipülasyonunun gerçekleştiği gerçek yaşam ortamlarında gerçekten kullanılamadığı ortaya çıktı.

Mükemmel çalışıyor:

/**
 * 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;
};

kodunuz doğru değil. İhtiyacınız görünmüyorsa orijinal öğenin, ifade eder. sizes = {"width": $wrap.width(), "height": $wrap.height()};this
jackJoe

@jackJoe Bu kodu bir süredir sorunsuz olarak kullanıyorum. En iyi ihtimalle 'this' yerine $ clone.width () 'a ihtiyacım olduğunu söyleyebilirim. Sargı içinde öğenin boyutunu istediğim için $ wrap değil. Ölçmek istediğim öğe örneğin 30x40px iken sarmalayıcı 10000x10000px olabilir.
Robin van Baalen

Hatta hedefleme $wraptamam (en azından benim testlerde). Ben denedim thisve tabii ki thishala gizli öğeye atıfta çünkü boyutu yakalamak olmaz .
jackJoe

1
Teşekkürler @jackJoe Şimdi kod örneğini güncelledim.
Robin van Baalen

12

Nick'in cevabına daha fazla odaklanmak:

$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").css({'position':'static','visibility':'visible', 'display':'none'});

Bunu yapmanın daha iyi olduğunu gördüm:

$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'});
optionHeight = $("#myDiv").height();
$("#myDiv").removeAttr('style');

CSS özniteliklerini ayarlamak, bunları satır içine ekler ve bu da CSS dosyanızdaki diğer özniteliklerin üzerine yazar. HTML öğesindeki stil niteliğini kaldırarak, her şey normale döner ve ilk başta gizlendiğinden hala gizlidir.


1
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'}); optionHeight = $("#myDiv").height(); $("#myDiv").css({'position':'','visibility':'', 'display':''});
Aaron

9
... öğe üzerinde zaten satır içi stiller yoksa. Elemanı jQuery ile saklarsanız durum böyle olur.
Muhd

4

Gizli div'ı display kullanmak yerine negatif bir kenar boşluğu ile ekranın dışına da konumlandırabilirsiniz: yok, bir metin girintisi görüntü değiştirme tekniği gibi.

Örneğin.

position:absolute;
left:  -2000px;
top: 0;

Bu şekilde height () hala kullanılabilir.


3

Gizli eleman için çalışma fonksiyonu bulmaya çalışıyorum ama CSS'nin herkesin düşündüğünden çok daha karmaşık olduğunu anlıyorum. CSS3'te, karmaşık üst öğe içindeki esnek kutu, ızgara, sütun veya hatta öğe gibi önceki tüm yanıtlar için çalışmayabilecek birçok yeni düzen tekniği vardır.

flexibox örneği resim açıklamasını buraya girin

Tek sürdürülebilir ve basit çözümün gerçek zamanlı renderleme olduğunu düşünüyorum . O zaman, tarayıcı size doğru eleman boyutunu vermelidir .

Ne yazık ki, JavaScript öğesi gösterildiğinde veya gizlendiğinde bildirimde bulunmak için doğrudan bir etkinlik sağlamaz. Ancak, öğenin görünürlüğü değiştiğinde geri arama işlevini yürütecek DOM Attribute Modified API'yi temel alan bazı işlevler oluşturuyorum.

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

    // render or adjust something
});

Daha fazla bilgi için, lütfen GitHub projemi ziyaret edin.

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

demo: http://jsbin.com/ETiGIre/7


Cevabınız için teşekkürler. MutationObservers'ı da kullanmam için bana ilham verdi. Ancak, kitaplığınızın yalnızca styleöznitelik değişikliklerinin neden olduğu görünürlük değişikliklerini kontrol ettiğini ( buradaki satır 59'a bakın ), görünürlük değişikliklerinin de classöznitelikteki değişikliklerden kaynaklandığını unutmayın.
Ashraf Sabry

Haklısın. Doğru ifade e.attributeName! == 'style' && e.attributeName! == 'className' olmalıdır
Soul_Master 24:14

2

Nick Craver'ın çözümünü takiben, elemanın görünürlüğünü ayarlamak doğru boyutlar elde etmesini sağlar. Bu çözümü çok sık kullandım. Ancak, stilleri manuel olarak sıfırlamak zorunda kaldım, geliştirme sırasında css'deki öğenin ilk konumlandırmasını / görüntüsünü değiştirdiğim için, genellikle ilgili javascript kodunu güncellemeyi unuttuğum göz önüne alındığında, bu hantal bulmaya geldim. Aşağıdaki kod, sözde stilleri sıfırlamaz, ancak javascript tarafından eklenen satır içi stilleri kaldırır:

$("#myDiv")
.css({
    position:   'absolute',
    visibility: 'hidden',
    display:    'block'
});

optionHeight = $("#myDiv").height();
optionWidth = $("#myDiv").width();

$("#myDiv").attr('style', '');

Buradaki tek varsayım, başka satır içi stiller olamaz ya da kaldırılacaktır. Bununla birlikte, buradaki avantaj, öğenin stillerinin css stil sayfasında oldukları şekilde döndürülmesidir. Sonuç olarak, bunu bir öğenin geçtiği ve yükseklik veya genişliğin döndürüldüğü bir işlev olarak yazabilirsiniz.

Stilleri js aracılığıyla satır içi olarak ayarlamayı bulduğum başka bir sorun, css3 yoluyla geçişlerle uğraşırken, stil kurallarınızın ağırlıklarını bazen sinir bozucu olabilecek satır içi bir stilden daha güçlü olacak şekilde uyarlamak zorunda kalmanızdır.


1

Tanım gereği, bir eleman yalnızca görünürse yüksekliğe sahiptir.

Sadece merak ediyorum: neden gizli bir elemanın yüksekliğine ihtiyacınız var?

Bir alternatif, bir öğeyi bir tür bindirmenin arkasına koyarak (z-endeksi kullanarak) etkili bir şekilde gizlemektir.


1
yüksekliğini istediğim süre boyunca gizli olan bir elemanın yüksekliğine ihtiyacım var. ben bir eklenti inşa ediyorum ve i init olarak bazı veri toplamak gerekiyor
mkoryak

2
başka bir neden henüz görünmeyen javascript ile şeyleri ortalamak için
Simon_Weaver

@cletus Sadece yorum yazmak istiyorsanız, gizli bir öğenin boyutunu almak için ön kodlamada çok sık karşılaşılan bir durumdur.
Rantiev

1

Benim durumumda, yükseklik değerini almamı engelleyen gizli bir öğem de vardı, ancak öğenin kendisi değil, ebeveynlerinden biri oldu ... bu yüzden eklentilerimden birinin gizli, aksi takdirde en yakın gizli öğeyi bulun. İşte bir örnek:

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');
    }
}

Aslında, bu, Nick, Gregory ve Eyelidlessness'in Gregory'nin gelişmiş yöntemini size vermesi için verdiği yanıtların bir birleşimidir, ancak stil özelliğinde geri koymak istediğiniz bir şey olması durumunda her iki yöntemi de kullanır ve arar. bir üst öğe.

Benim çözümümdeki tek sıkıntı, ebeveynler arasındaki döngünün tamamen verimli olmamasıdır.


1

Çözümlerden biri, yüksekliğini almak istediğiniz öğenin dışında bir üst div oluşturmak, '0' yüksekliğini uygulamak ve taşmayı gizlemektir. Ardından, alt öğenin yüksekliğini alın ve üst öğenin taşma özelliğini kaldırın.

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>


0

İşte gizli elemanlar, hatta gizli ebeveynlerin torunları için jQuery'nin tüm boyut yöntemlerini ele almak için yazdığım bir komut dosyası. Elbette, bunu kullanarak bir performans isabeti olduğunu unutmayın.

// 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);

Göz kapaksızlığının cevabı ihtiyacım olan şey için mükemmel görünüyor, ancak çalıştırdığım jQuery ile çalışmıyor: 1.3.2 jQuery'nin bir this.clone (veya çok yakın bir şey) atmasına neden oluyor. Nasıl düzeltebileceğine dair bir fikriniz var mı?

0

Öğeyi daha önce sayfada görüntülediyseniz, yüksekliği doğrudan DOM öğesinden (jQuery'de .get (0) ile erişilebilir) alabilirsiniz, çünkü öğe gizlenmiş olsa bile ayarlanmıştır:

$('.hidden-element').get(0).height;

genişlik için aynı:

$('.hidden-element').get(0).width;

(düzeltme için Skeets O'Reilly'e teşekkürler)


İadeundefined
Jake Wilson

1
Bunun yalnızca öğeyi daha önce sayfada görüntülediyseniz işe yarar. Her zaman var olan elemanlar için bu display='none'işe yaramaz.
Skeets
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.