jQuery: получить высоту скрытого элемента в jQuery
Мне нужно получить высоту элемента, который находится в div, который скрыт. Прямо сейчас я показываю div, получаю высоту и скрываю Родительский div. Это кажется немного глупым. Есть ли лучший способ?
Я использую jQuery 1.4.2:
$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
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
Я думаю, что единственным устойчивым и простым решением является рендеринг в реальном времени. В то время браузер должен дать вам это правильный размер элемента.
к сожалению, JavaScript не предоставляет никаких прямых событий для уведомления, когда элемент отображается или скрыт. Однако я создаю некоторую функцию на основе измененного API атрибута DOM, которая будет выполнять функцию обратного вызова при изменении видимости элемента.
$('[selector]').onVisibleChanged(function(e, isVisible) { var realWidth = $('[selector]').width(); var realHeight = $('[selector]').height(); // render or adjust something });для получения дополнительной информации, пожалуйста, посетите мой проект GitHub.
по определению, элемент имеет высоту только в том случае, если он виден.
просто любопытно: зачем вам нужна высота скрытого элемента?
одна эффективно скрыть элемент, поставив его позади (используя 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;(спасибо Скитс О'Рейли для исправления)

Comments