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



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



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



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

15 ответов:

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

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

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

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

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

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

полная документация см. здесь. Существует также демо-включить в страницу.

надеюсь, что это поможет :)

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

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

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

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

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

дальнейшее развитие ответа Ника:

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

основываясь далее на ответе пользователя Ника и плагине пользователя 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;
};

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

например.

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

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

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

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

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

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

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

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

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

пример flexibox enter image description here

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

к сожалению, JavaScript не предоставляет никаких прямых событий для уведомления, когда элемент отображается или скрыт. Однако я создаю некоторую функцию на основе измененного API атрибута DOM, которая будет выполнять функцию обратного вызова при изменении видимости элемента.

$('[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

по определению, элемент имеет высоту только в том случае, если он виден.

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

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

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

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

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

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

один обходной путь состоит в том, чтобы создать родительский div вне элемента, который вы хотите получить высоту, применить высоту '0' и скрыть любое переполнение. Затем возьмите высоту дочернего элемента и удалите свойство overflow родительского элемента.

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;

(спасибо Скитс О'Рейли для исправления)

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

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

Comments

    Ничего не найдено.