JQuery: получить высоту скрытого элемента в jQuery

Мне нужно получить высоту элемента, который находится внутри div, который скрыт. Прямо сейчас я показываю div, получаю высоту и скрываю родительский div. Это кажется немного глупым. Есть ли лучший способ?

Я использую jQuery 1.4.2:

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

Ответ 1

Вы можете сделать что-то вроде этого, хотя и немного странно, забыть 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 : "");

Ответ 2

Я столкнулся с той же проблемой с получением ширины скрытого элемента, поэтому я написал этот плагиновый вызов jQuery Actual, чтобы исправить это. Вместо использования

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

использовать

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

даст вам правильное значение для скрытого элемента или элемент имеет скрытый родительский элемент.

Полная документация смотрите здесь . На странице также есть демо.

Надеюсь, что эта помощь:)

Ответ 3

Вы смешиваете два стиля CSS, стиль и видимость стиль.

Если элемент скрыт, установив стиль css видимости, вы должны иметь возможность получать высоту независимо от того, является ли элемент видимым или нет, поскольку элемент по-прежнему занимает пробел на странице.

Если элемент скрыт, изменив стиль отображения CSS на "none", тогда элемент не займет пробела на странице, и вам придется придать ему стиль отображения, который заставит элемент визуализировать в некоторых пространство, с которого вы можете получить высоту.

Ответ 4

Я на самом деле прибегал к немного обману, чтобы справляться с этим время от времени. Я разработал виджет прокрутки 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 для определения соответствующей ширины родительского элемента.

Ответ 5

Следуя дальше, ответьте Нику:

$("#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, все возвращается в нормальное состояние и все еще скрыто, поскольку оно было спрятано в первую очередь.

Ответ 6

Основываясь далее на пользовательском ответе Ника и пользовательском плагине hitautodestruct на JSBin, я создал аналогичный плагин 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 <[email protected]>
 * @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;
};

Ответ 7

Вы также можете поместить скрытый div с экрана с отрицательным полем, а не с помощью дисплея: none, очень похожим на метод замены текста в отступом.

например.

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

Таким образом, высота() все еще доступна.

Ответ 8

Следующее решение Nick Craver, настройка видимости элемента позволяет получать точные размеры. Я использовал это решение очень часто. Однако, имея reset стили вручную, я пришел, чтобы найти это громоздко, учитывая, что изменение начального позиционирования/отображения элемента в моем css через разработку часто забываю обновить связанный код javascript. Следующий код не содержит reset стилей за отзыв, но удаляет встроенные стили, добавленные javascript:

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

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

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

Единственное предположение здесь состоит в том, что не может быть других встроенных стилей, иначе они также будут удалены. Преимущество здесь, однако, в том, что стили элементов возвращаются к тому, что они были в таблице стилей css. Как следствие, вы можете записать это как функцию, в которой проходит элемент, и возвращается высота или ширина.

Еще одна проблема, связанная с установкой стилей inline через js, заключается в том, что при работе с переходами через css3 вы вынуждены адаптировать весы правил стиля, чтобы быть сильнее, чем встроенный стиль, который иногда может быть неприятным.

Ответ 9

Я пытаюсь найти рабочую функцию для скрытого элемента, но я понимаю, что CSS очень сложный, чем все думают. В CSS3 есть много новых методов компоновки, которые могут не работать для всех предыдущих ответов, таких как гибкий ящик, сетка, столбец или четный элемент внутри сложного родительского элемента.

пример flexibox enter image description here

Я думаю, что единственным устойчивым и простым решением является рендеринг в реальном времени. В то время браузер должен предоставить вам правильный размер элемента.

К сожалению, JavaScript не предоставляет никакого прямого события для уведомления, когда элемент отображается или скрыт. Тем не менее, я создаю некоторую функцию, основанную на DOM Attribute Modified 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

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

Ответ 10

По определению элемент имеет высоту, если он виден.

Просто любопытно: зачем вам высоту скрытого элемента?

Один из вариантов заключается в том, чтобы эффективно скрыть элемент, поместив его (используя z-index) наложение какого-то типа).

Ответ 11

В моих обстоятельствах у меня также был скрытый элемент, который мешал мне получить значение высоты, но это был не сам элемент, а скорее один из его родителей... поэтому я просто поставил чек на один из моих плагинов посмотрите, скрыта ли она, и найдите ближайший скрытый элемент. Вот пример:

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

На самом деле, это объединение ответов Ника, Грегори и Безумие, чтобы дать вам использование улучшенного метода Грегори, но использует оба метода в случае, если предполагается, что что-то есть в атрибуте стиля, который вы хотите вернуть, и ищет родительский элемент.

Моя единственная проблема с моим решением заключается в том, что цикл через родителей не совсем эффективен.

Ответ 12

Одним из способов является создание родительского 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>

Ответ 13

Здесь script я написал для обработки всех методов измерения 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);

Ответ 14

Если вы уже показывали элемент на предыдущей странице, вы можете просто взять высоту непосредственно из элемента DOM (доступного в jQuery с .get(0)), поскольку он установлен даже тогда, когда элемент скрыт:

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

одинаково для ширины:

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

(спасибо Skeets O'Reilly за исправление)

Ответ 15

$('#idOfElement').height();

//, чтобы найти высоту