我需要获取处于隐藏的div内的元素的高度。现在,我显示div,获取高度,并隐藏父div。这似乎有点愚蠢。有没有更好的办法?
我正在使用jQuery 1.4.2:
$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
我需要获取处于隐藏的div内的元素的高度。现在,我显示div,获取高度,并隐藏父div。这似乎有点愚蠢。有没有更好的办法?
我正在使用jQuery 1.4.2:
$select.show();
optionHeight = $firstOption.height(); //we can only get height if its visible
$select.hide();
Answers:
您可以执行以下操作,虽然有点怪异,但请记住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 : "");
position:relative
,则当然要在之后设置而不是static
。
我遇到了隐藏元素宽度的相同问题,因此我编写了此插件调用jQuery Actual来修复它。而不是使用
$('#some-element').height();
用
$('#some-element').actual('height');
将为隐藏元素或具有隐藏父元素的元素提供正确的值。
希望这个帮助:)
如果通过设置可见性css样式隐藏了元素,则无论元素是否可见,您都应该能够获得高度,因为该元素仍在页面上占据空间。
如果通过将display css样式更改为“ none”来隐藏该元素,则该元素不会在页面上占用空间,并且您将不得不给它一种显示样式,这将导致该元素在某个空间处呈现。哪一点就可以得到高度。
visibility
为hidden
并不能解决我的问题,但这给了我进行设置的想法position: fixed; top: 100%
,它的工作原理很吸引人!
实际上,我有时会采取一些技巧来解决这个问题。我开发了一个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规则,其中不包括对父标记的引用。
另外,我的滚动器小部件并没有解决这个问题,但是要获得适当的克隆元素高度,您需要将宽度设置为与父元素相同的宽度。就我而言,CSS宽度始终应用于实际元素,因此我不必担心这一点,但是,如果元素没有对其应用宽度,则可能需要进行某种递归遍历元素的DOM祖先以找到适当的父元素的宽度。
在用户Nick的答案和JSBin上的用户hitautodestruct的插件的基础上,我创建了一个类似的jQuery插件,该插件可同时检索width和height并返回包含这些值的对象。
可以在这里找到: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;
};
sizes = {"width": $wrap.width(), "height": $wrap.height()};
的this
是指原来的项目,这是不可见的。
$wrap
可以的(至少在我的测试中如此)。我尝试使用this
,显然它无法捕捉大小,因为它this
仍然引用隐藏的元素。
进一步根据尼克的答案:
$("#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元素上的style属性,所有内容都恢复了正常,并且仍然隐藏,因为它首先隐藏了。
$("#myDiv").css({'position':'absolute','visibility':'hidden', 'display':'block'}); optionHeight = $("#myDiv").height(); $("#myDiv").css({'position':'','visibility':'', 'display':''});
我试图找到隐藏元素的工作功能,但是我意识到CSS比每个人都想的复杂得多。CSS3中有很多新的布局技术,可能不适用于所有先前的答案,例如灵活的框,网格,列甚至复杂父元素中的元素。
flexibox示例
我认为唯一可持续和简单的解决方案是实时渲染。那时,浏览器应该为您提供正确的元素大小。
可悲的是,JavaScript不提供任何直接事件来通知元素是显示还是隐藏。但是,我基于DOM Attribute Modified API创建了一些函数,当元素的可见性更改时,该函数将执行回调函数。
$('[selector]').onVisibleChanged(function(e, isVisible)
{
var realWidth = $('[selector]').width();
var realHeight = $('[selector]').height();
// render or adjust something
});
有关更多信息,请访问我的项目GitHub。
style
属性更改引起的可见性更改(请参见此处的第59行),而可见性更改也可能是由属性更改引起的class
。
根据Nick Craver的解决方案,设置元素的可见性可以使其获得准确的尺寸。我经常使用此解决方案。但是,由于必须手动重置样式,因此我发现这样做很麻烦,因为通过开发修改元素在CSS中的初始位置/显示,我经常忘记更新相关的javascript代码。以下代码不会重设每个提示的样式,但会删除javascript添加的内联样式:
$("#myDiv")
.css({
position: 'absolute',
visibility: 'hidden',
display: 'block'
});
optionHeight = $("#myDiv").height();
optionWidth = $("#myDiv").width();
$("#myDiv").attr('style', '');
这里唯一的假设是不能有其他内联样式,否则它们也会被删除。但是,这样做的好处是,元素的样式恢复为CSS样式表中的样式。因此,您可以将其编写为一个函数,在其中传递元素,并返回高度或宽度。
我发现通过js内联设置样式的另一个问题是,在通过css3处理过渡时,您不得不适应于更改样式规则的权重,使其比内联样式更强,这有时会令人沮丧。
根据定义,元素只有在可见时才具有高度。
只是好奇:为什么需要隐藏元素的高度?
一种替代方法是通过将元素放置在某种类型的叠加层之后(使用z-index)来有效地隐藏它。
在我的情况下,我还有一个隐藏的元素阻止我获取高度值,但这不是元素本身,而是它的父元素之一...所以我只是检查了我的一个插件,看是否是隐藏,否则找到最接近的隐藏元素。这是一个例子:
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');
}
}
实际上,这是Nick,Gregory和Eyelidlessness的响应的合并,以使您可以使用Gregory的改进方法,但是要同时使用两种方法,以防样式属性中有您想放回的东西并寻找父元素。
我对解决方案的唯一困扰是,通过父母的循环并不完全有效。
一种解决方法是在要获取高度的元素外部创建父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>
这是我编写的脚本,用于处理jQuery的所有隐藏元素,甚至隐藏父级后代的Dimension方法。请注意,使用此功能当然会对性能产生影响。
// 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);