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 и фактический исправить. Вместо использования
$('#some-element').height();
использовать
$('#some-element').actual('height');
даст вам правильное значение для скрытого элемента или элемента имеет скрытый родитель.
полную документацию см. здесь. Существует также демо включают в себя на странице.
надеюсь, что это поможет :)
вы confuising двух стилей CSS, тег тип дисплея и стиль видимость.
Если элемент скрыт, установив стиль видимости css, то вы должны иметь возможность получить высоту независимо от того, является ли элемент видимым или нет, как элемент по-прежнему занимает место на странице.
Если элемент скрыт, изменив стиль отображения css на "нет", то элемент не занимает места на странице, и вам нужно будет дать ему стиль отображения, который заставит элемент отображаться в некотором пространстве, и в этот момент Вы можете получить высоту.
Я на самом деле прибегал к некоторым трюкам, чтобы справиться с этим время от времени. Я разработал виджет прокрутки jQuery, где я столкнулся с проблемой, которую я не знаю заранее, является ли прокручиваемый контент частью скрытой части разметки или нет. Вот что я сделал:--2-->
// 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 <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;
};
вы также можете поместить скрытый div с экрана с отрицательным полем, а не с помощью display:none, как и метод замены отступа текста.
например.
position:absolute;
left: -2000px;
top: 0;
таким образом, height() по-прежнему доступен.
следуя решению Ника Крейвера, настройка видимости элемента позволяет получить точные размеры. Я использовал это решение очень часто. Однако, чтобы сбросить стили вручную, я пришел, чтобы найти это громоздким, учитывая, что изменение начального позиционирования/отображения элемента в моем css через разработку, я часто забываю обновить соответствующий код javascript. Следующий код не сбрасывает стили за say, но удаляет встроенные стили, добавленные 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');
}
}
на самом деле, это объединение ответов Ника, Грегори и Eyelidless, чтобы дать вам использование улучшенного метода Грегори, но использует оба метода в случае, если есть предполагается, что что-то в атрибуте style, который вы хотите вернуть, и ищет родительский элемент.
моя единственная проблема с моим решением заключается в том, что цикл через родителей не совсем эффективен.
один обходной путь-создать родительский 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 with .get (0)), так как он установлен даже тогда, когда элемент скрыт:
$('.hidden-element').get(0).height;
то же самое для ширины:
$('.hidden-element').get(0).width;
(спасибо Скитс О'Рейли для исправления)