jQuery: Dapatkan ketinggian elemen tersembunyi di jQuery


249

Saya perlu mendapatkan ketinggian elemen yang ada di dalam div yang tersembunyi. Saat ini saya menunjukkan div, dapatkan ketinggian, dan menyembunyikan div induk. Ini agak konyol. Apakah ada cara yang lebih baik?

Saya menggunakan jQuery 1.4.2:

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

42
+1 Solusi contoh Anda sebenarnya lebih baik daripada semua jawaban yang ada.
Tim Santeford

9
Saya tidak setuju Tim. Dengan solusi ini, ada kemungkinan layar akan berkedip karena Anda benar-benar menunjukkan item dan kemudian menyembunyikannya. Meskipun solusi Nicks lebih berbelit-belit, ia tidak memiliki peluang untuk mengedipkan layar karena div induk tidak pernah ditampilkan.
Humphrey



5
Harry, sebenarnya yang Anda temukan adalah kode Anda tidak berfungsi di IE, bukan solusi ini. Go debug kode Anda :)
Gavin

Jawaban:


181

Anda dapat melakukan sesuatu seperti ini, agak sedikit hacky, lupa positionjika itu sudah mutlak:

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
Saya menggabungkan kode di atas ke dalam plugin jQ jsbin.com/ihakid/2 . Saya juga menggunakan kelas dan memeriksa apakah orang tua juga tersembunyi.
hitautodestruct

3
+1 Ini sangat bagus. Hanya perlu diingat bahwa elemen orang tua harus ditampilkan juga. Ini membuat saya bingung selama beberapa menit. Juga, jika elemennya adalah position:relative, tentu saja Anda ingin menyetelnya setelahnya static.
Michael Mior

6
Saat Anda menggunakan metode ini, elemen target seringkali dapat berubah bentuk. Jadi mendapatkan tinggi dan / atau lebar div ketika benar-benar diposisikan mungkin tidak terlalu berguna.
Jeremy Ricketts

2
@ Gavin ini mencegah perhitungan reflow dan flicker apa pun kepada pengguna, sehingga lebih murah dan tidak terlalu mengganggu.
Nick Craver

2
@hitautodestruct, saya telah memodifikasi plugin kueri Anda untuk memeriksa ini hanya elemen yang sebenarnya disembunyikan. jsbin.com/ihakid/58
Prasad

96

Saya mengalami masalah yang sama dengan mendapatkan lebar elemen tersembunyi, jadi saya menulis panggilan plugin ini jQuery Actual untuk memperbaikinya. Alih-alih menggunakan

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

menggunakan

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

akan memberi Anda nilai yang tepat untuk elemen tersembunyi atau elemen memiliki induk tersembunyi.

Dokumentasi lengkap silakan lihat di sini . Ada juga demo termasuk di halaman.

Semoga bantuan ini :)


3
Ya itu membantu! 2015 dan itu masih membantu. Anda mengatakan "versi jquery yang lebih lama" di situs web Actual - namun - itu masih diperlukan di v2.1.3, setidaknya itu dalam situasi saya.
LpLrich

Terima kasih! Saya menggunakan plugin ini untuk membaca dan mengatur ketinggian elemen (ini dilakukan secara dinamis) disembunyikan pada awalnya dalam akordeon
alds

Plugin luar biasa! Saya mencoba segalanya untuk mendapatkan lebar div di dalam modal ketika diatur ke 100% dan tidak ada yang berhasil. atur ini dalam 5 detik dan bekerja dengan sempurna!
Craig Howell

@ben Tautan rusak.
Sachin Prasad

39

Anda mengonfigurasikan dua gaya CSS, gaya tampilan dan gaya visibilitas .

Jika elemen disembunyikan dengan mengatur gaya visibilitas css, maka Anda harus bisa mendapatkan ketinggian terlepas dari apakah elemen tersebut terlihat atau tidak karena elemen tersebut masih membutuhkan ruang pada halaman .

Jika elemen disembunyikan dengan mengubah gaya tampilan css ke "tidak ada", maka elemen tidak mengambil ruang pada halaman, dan Anda harus memberikannya gaya tampilan yang akan menyebabkan elemen untuk membuat di beberapa ruang, di titik mana, Anda bisa mendapatkan ketinggian.


Terima kasih untuk ini. masalah saya melibatkan sel tabel, dan pengaturan visibilityuntuk hiddentidak menyelesaikan masalah saya, tapi itu memberi saya ide untuk mengatur position: fixed; top: 100%dan itu berfungsi seperti pesona!
Jayen

Sekarang saya mengerti mengapa tingginya tidak ditampilkan dengan tampilan: tidak ada elemen. Terima kasih banyak atas penjelasannya.
FrenkyB

30

Saya sebenarnya telah menggunakan sedikit tipu daya untuk menghadapi ini di kali. Saya mengembangkan widget scrollbar jQuery di mana saya menemukan masalah yang tidak saya ketahui sebelumnya jika konten yang dapat digulirkan adalah bagian dari markup tersembunyi atau tidak. Inilah yang saya lakukan:

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

Ini berfungsi sebagian besar, tetapi ada masalah yang jelas yang berpotensi muncul. Jika konten yang Anda kloning ditata dengan CSS yang menyertakan referensi ke markup induk dalam aturan mereka, konten yang dikloning tidak akan berisi gaya yang sesuai, dan kemungkinan akan memiliki pengukuran yang sedikit berbeda. Untuk menyiasatinya, Anda dapat memastikan bahwa markup yang Anda kloning menerapkan aturan CSS yang tidak menyertakan referensi ke markup induk.

Juga, ini tidak muncul untuk saya dengan widget scroller saya, tetapi untuk mendapatkan ketinggian yang sesuai dari elemen yang dikloning, Anda harus mengatur lebar dengan lebar yang sama dari elemen induk. Dalam kasus saya, lebar CSS selalu diterapkan pada elemen aktual, jadi saya tidak perlu khawatir tentang ini, namun, jika elemen tidak memiliki lebar diterapkan untuk itu, Anda mungkin perlu melakukan beberapa jenis rekursif lintasan leluhur DOM elemen untuk menemukan lebar elemen induk yang sesuai.


Ini memiliki masalah yang menarik. Jika elemen sudah menjadi elemen blok, clone akan mengambil seluruh lebar tubuh (kecuali body padding atau margin), yang berbeda dari ukurannya di dalam wadah.
Meligy

16

Membangun lebih lanjut tentang jawaban pengguna Nick dan plugin pengguna hitautodestruct di JSBin, saya telah membuat plugin jQuery serupa yang mengambil lebar dan tinggi dan mengembalikan objek yang berisi nilai-nilai ini.

Itu dapat ditemukan di sini: http://jsbin.com/ikogez/3/

Memperbarui

Saya telah sepenuhnya mendesain ulang plugin kecil ini karena ternyata versi sebelumnya (yang disebutkan di atas) tidak benar-benar dapat digunakan di lingkungan kehidupan nyata di mana banyak manipulasi DOM terjadi.

Ini berfungsi dengan baik:

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

kode Anda tidak benar. Anda perlu sizes = {"width": $wrap.width(), "height": $wrap.height()};yang thismengacu pada item asli, yang tidak terlihat.
jackJoe

@JackJoe Saya telah menggunakan kode ini untuk beberapa waktu tanpa masalah. Paling-paling saya akan mengatakan saya perlu $ clone.width () bukannya 'ini'. Bukan $ wrap karena saya ingin ukuran elemen di dalam bungkus. Wrapper bisa berukuran 10000x10000px sedangkan elemen yang ingin saya ukur masih 30x40px misalnya.
Robin van Baalen

Bahkan menargetkan $wraptidak apa-apa (setidaknya dalam tes saya). Saya mencoba dengan thisdan jelas tidak akan menangkap ukuran karena thismasih mengacu pada elemen tersembunyi.
jackJoe

1
Terima kasih @jackJoe Sekarang saya telah memperbarui contoh kode.
Robin van Baalen

12

Membangun lebih jauh jawaban Nick:

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

Saya menemukan lebih baik melakukan ini:

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

Mengatur atribut CSS akan memasukkannya secara inline, yang akan menimpa atribut lain yang Anda miliki di file CSS Anda. Dengan menghapus atribut style pada elemen HTML, semuanya kembali normal dan masih tersembunyi, karena itu disembunyikan di tempat pertama.


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

9
... kecuali Anda sudah memiliki gaya sebaris pada elemen. Yang akan terjadi jika Anda menyembunyikan elemen dengan jQuery.
Muhd

4

Anda juga bisa memposisikan div tersembunyi dari layar dengan margin negatif daripada menggunakan tampilan: tidak ada, seperti teknik penggantian gambar indentasi teks.

misalnya.

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

Dengan cara ini ketinggian () masih tersedia.


3

Saya mencoba menemukan fungsi kerja untuk elemen tersembunyi tetapi saya menyadari bahwa CSS jauh lebih kompleks daripada yang dipikirkan semua orang. Ada banyak teknik tata letak baru di CSS3 yang mungkin tidak berfungsi untuk semua jawaban sebelumnya seperti kotak fleksibel, kisi, kolom atau bahkan elemen di dalam elemen induk kompleks.

contoh flexibox masukkan deskripsi gambar di sini

Saya pikir satu-satunya solusi yang berkelanjutan & sederhana adalah rendering waktu-nyata . Pada saat itu, browser seharusnya memberi Anda ukuran elemen yang benar .

Sayangnya, JavaScript tidak menyediakan acara langsung untuk memberi tahu ketika elemen ditampilkan atau disembunyikan. Namun, saya membuat beberapa fungsi berdasarkan DOM Attribute Modified API yang akan menjalankan fungsi callback ketika visibilitas elemen diubah.

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

    // render or adjust something
});

Untuk informasi lebih lanjut, Silakan kunjungi di proyek saya GitHub.

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

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


Terima kasih atas jawaban anda. Itu mengilhami saya untuk menggunakan MutationObservers juga. Tetapi perhatikan bahwa perpustakaan Anda memeriksa hanya untuk perubahan visibilitas yang disebabkan oleh styleperubahan atribut (lihat baris 59 di sini ), sementara perubahan visibilitas mungkin juga disebabkan oleh perubahan classatribut.
Ashraf Sabry

Kamu benar. Pernyataan yang benar adalah e.attributeName! == 'style' && e.attributeName! == 'className'
Soul_Master

2

Mengikuti solusi Nick Craver, mengatur visibilitas elemen memungkinkannya mendapatkan dimensi yang akurat. Saya telah menggunakan solusi ini sangat sering. Namun, karena harus mengatur ulang gaya secara manual, saya datang untuk menemukan ini rumit, mengingat bahwa memodifikasi posisi / tampilan awal elemen dalam css saya melalui pengembangan, saya sering lupa untuk memperbarui kode javascript terkait. Kode berikut tidak menyetel ulang gaya per kata, tetapi menghapus gaya sebaris yang ditambahkan oleh javascript:

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

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

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

Satu-satunya asumsi di sini adalah bahwa tidak mungkin ada gaya inline lainnya atau mereka akan dihapus juga. Manfaatnya di sini, bagaimanapun, adalah bahwa gaya elemen dikembalikan ke apa yang ada di lembar style css. Sebagai konsekuensinya, Anda dapat menulis ini sebagai fungsi di mana elemen dilewati, dan tinggi atau lebar dikembalikan.

Masalah lain yang saya temukan tentang pengaturan gaya inline via js adalah bahwa ketika berhadapan dengan transisi melalui css3, Anda menjadi dipaksa untuk menyesuaikan bobot aturan gaya Anda menjadi lebih kuat daripada gaya inline, yang kadang-kadang bisa membuat frustrasi.


1

Menurut definisi, suatu elemen hanya memiliki tinggi jika terlihat.

Hanya ingin tahu: mengapa Anda membutuhkan ketinggian elemen tersembunyi?

Salah satu alternatif adalah menyembunyikan elemen secara efektif dengan meletakkannya di belakang (menggunakan z-index) semacam overlay).


1
Saya perlu ketinggian elemen, yang disembunyikan selama saya ingin tingginya. saya sedang membangun sebuah plugin dan saya perlu mengumpulkan beberapa data saat saya menggunakannya
mkoryak

2
alasan lain adalah untuk memusatkan hal-hal dengan javascript yang mungkin belum terlihat
Simon_Weaver

@cletus Jika Anda hanya ingin menulis komentar, itu sangat sering situasi di frontend coding untuk mendapatkan ukuran elemen tersembunyi.
Rantiev

1

Dalam keadaan saya, saya juga memiliki elemen tersembunyi yang menghentikan saya dari mendapatkan nilai tinggi, tapi itu bukan elemen itu sendiri melainkan salah satu dari orang tuanya ... jadi saya hanya memberi tanda centang pada salah satu plugin saya untuk melihat apakah itu disembunyikan, kalau tidak temukan elemen tersembunyi terdekat. Ini sebuah contoh:

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

Sebenarnya, ini adalah gabungan dari tanggapan Nick, Gregory dan Eyelidlessness untuk memberi Anda penggunaan metode yang ditingkatkan Gregory, tetapi menggunakan kedua metode jika ada sesuatu dalam atribut gaya yang ingin Anda kembalikan, dan mencari elemen induk.

Satu-satunya keluhan saya dengan solusi saya adalah bahwa perulangan melalui orang tua tidak sepenuhnya efisien.


1

Salah satu solusinya adalah membuat div induk di luar elemen yang Anda inginkan, terapkan ketinggian '0' dan sembunyikan semua luapan. Selanjutnya, ambil ketinggian elemen anak dan hapus properti overflow induknya.

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

Berikut ini skrip yang saya tulis untuk menangani semua metode dimensi jQuery untuk elemen tersembunyi, bahkan keturunan orang tua yang tersembunyi. Perhatikan bahwa, tentu saja, ada hit kinerja menggunakan ini.

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

Jawaban oleh kelopak mata terlihat sempurna untuk apa yang saya butuhkan tetapi tidak bekerja dengan jQuery yang saya jalankan: 1.3.2 Ini menyebabkan jQuery untuk melempar this.clone (atau sesuatu yang sangat dekat) bukan fungsi. Adakah yang punya ide tentang cara memperbaikinya?

0

Jika Anda sudah menampilkan elemen pada halaman sebelumnya, Anda bisa langsung mengambil tinggi dari elemen DOM (dapat dijangkau dalam jQuery dengan .get (0)), karena ia disetel bahkan ketika elemen disembunyikan:

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

sama untuk lebar:

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

(Terima kasih kepada Skeets O'Reilly untuk koreksi)


Pengembalianundefined
Jake Wilson

1
Cukup yakin ini hanya berfungsi jika Anda sudah menampilkan elemen pada halaman sebelumnya. Untuk elemen yang selalu ada display='none', ini tidak akan berhasil.
Skeets
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.