似乎在jQuery中,当元素不可见时,width()返回0.有道理,但我需要获取表的宽度,以便在显示父级之前设置父级的宽度。
如下所述,父母中有文字,使父母倾斜并且看起来很讨厌。我希望父级只能与表格一样宽,并且包含文本。
<div id="parent">
Text here ... Can get very long and skew the parent
<table> ... </table>
Text here too ... which is why I want to shrink the parent based on the table
</div>
CSS:
#parent
{
display: none;
}
使用Javascript:
var tableWidth = $('#parent').children('table').outerWidth();
if (tableWidth > $('#parent').width())
{
$('#parent').width(tableWidth);
}
tableWidth总是返回0,因为它不可见(我猜是因为它在可见时给了我一个数字)。有没有办法获得表格的宽度而不使父母可见?
答案 0 :(得分:91)
这是我用过的一个技巧。它涉及添加一些CSS属性以使jQuery认为元素是可见的,但事实上它仍然是隐藏的。
var $table = $("#parent").children("table");
$table.css({ position: "absolute", visibility: "hidden", display: "block" });
var tableWidth = $table.outerWidth();
$table.css({ position: "", visibility: "", display: "" });
这是一种黑客行为,但似乎对我来说很好。
<强>更新强>
我已经写了一篇涵盖这个主题的blog post。由于您要将CSS属性重置为空值,因此上面使用的方法可能会出现问题。如果他们之前有价值怎么办?更新的解决方案使用jQuery源代码中的swap()方法。
参考博客文章中的代码:
//Optional parameter includeMargin is used when calculating outer dimensions
(function ($) {
$.fn.getHiddenDimensions = function (includeMargin) {
var $item = this,
props = { position: 'absolute', visibility: 'hidden', display: 'block' },
dim = { width: 0, height: 0, innerWidth: 0, innerHeight: 0, outerWidth: 0, outerHeight: 0 },
$hiddenParents = $item.parents().andSelf().not(':visible'),
includeMargin = (includeMargin == null) ? false : includeMargin;
var oldProps = [];
$hiddenParents.each(function () {
var old = {};
for (var name in props) {
old[name] = this.style[name];
this.style[name] = props[name];
}
oldProps.push(old);
});
dim.width = $item.width();
dim.outerWidth = $item.outerWidth(includeMargin);
dim.innerWidth = $item.innerWidth();
dim.height = $item.height();
dim.innerHeight = $item.innerHeight();
dim.outerHeight = $item.outerHeight(includeMargin);
$hiddenParents.each(function (i) {
var old = oldProps[i];
for (var name in props) {
this.style[name] = old[name];
}
});
return dim;
}
}(jQuery));
答案 1 :(得分:40)
function realWidth(obj){
var clone = obj.clone();
clone.css("visibility","hidden");
$('body').append(clone);
var width = clone.outerWidth();
clone.remove();
return width;
}
realWidth($("#parent").find("table:first"));
答案 2 :(得分:8)
根据罗伯茨的回答,这是我的功能。 如果元素或其父元素已经通过jQuery淡出,这对我有用,可以获得内部或外部维度,也可以返回偏移值。
/ edit1:重写了这个函数。它现在变小了,可以直接在对象上调用
/ edit2:该函数现在将在原始元素之后插入克隆而不是正文,从而使克隆可以维持继承的维度。
$.fn.getRealDimensions = function (outer) {
var $this = $(this);
if ($this.length == 0) {
return false;
}
var $clone = $this.clone()
.show()
.css('visibility','hidden')
.insertAfter($this);
var result = {
width: (outer) ? $clone.outerWidth() : $clone.innerWidth(),
height: (outer) ? $clone.outerHeight() : $clone.innerHeight(),
offsetTop: $clone.offset().top,
offsetLeft: $clone.offset().left
};
$clone.remove();
return result;
}
var dimensions = $('.hidden').getRealDimensions();
答案 3 :(得分:3)
感谢您发布上面的realWidth函数,它真的帮到了我。 基于上面的“realWidth”函数,我写了一个CSS重置,(原因如下所述)。
function getUnvisibleDimensions(obj) {
if ($(obj).length == 0) {
return false;
}
var clone = obj.clone();
clone.css({
visibility:'hidden',
width : '',
height: '',
maxWidth : '',
maxHeight: ''
});
$('body').append(clone);
var width = clone.outerWidth(),
height = clone.outerHeight();
clone.remove();
return {w:width, h:height};
}
“realWidth”获取现有标记的宽度。我用一些图像标签对此进行了测试。问题是,当图像每宽度(或最大宽度)给出CSS尺寸时,您将永远无法获得该图像的真实尺寸。也许,img具有“max-width:100%”,“realWidth”函数克隆它并将其附加到正文。 如果图像的原始大小比正文大,那么您将获得正文的大小而不是该图像的实际大小。
答案 4 :(得分:3)
我试图找到隐藏元素的工作函数,但我意识到CSS比每个人都想象的要复杂得多。 CSS3中有许多新的布局技术可能不适用于所有先前的答案,如灵活的框,网格,列或复杂父元素内的元素。
flexibox示例
我认为唯一可持续的&amp;简单的解决方案是实时渲染。那时,浏览器应该为您提供正确的元素大小。
可悲的是,JavaScript在显示或隐藏元素时不提供任何直接事件通知。但是,我创建了一些基于DOM Attribute Modified API的函数,当元素的可见性发生变化时,它将执行回调函数。
$('[selector]').onVisibleChanged(function(e, isVisible)
{
var realWidth = $('[selector]').width();
var realHeight = $('[selector]').height();
// render or adjust something
});
有关详细信息,请访问我的项目GitHub。
答案 5 :(得分:3)
如果您需要隐藏的内容的宽度而无法以任何原因取消隐藏它,您可以克隆它,更改CSS以使其显示在页面外,使其不可见,然后进行测量。如果用户隐藏并随后删除,则用户将不会更聪明。
这里的其他一些答案只是隐藏了可见性,但它会在页面上占据一个空白点,只需几分之一秒。
示例:
$itemClone = $('.hidden-item').clone().css({
'visibility': 'hidden',
'position': 'absolute',
'z-index': '-99999',
'left': '99999999px',
'top': '0px'
}).appendTo('body');
var width = $itemClone.width();
$itemClone.remove();
答案 6 :(得分:2)
在取宽度使父显示显示之前,然后取宽度,最后使父显示隐藏。就像下面的
$('#parent').show();
var tableWidth = $('#parent').children('table').outerWidth();
$('#parent').hide();
if (tableWidth > $('#parent').width())
{
$('#parent').width() = tableWidth;
}
答案 7 :(得分:2)
一种解决方案,虽然它在所有情况下都不起作用,但是通过将不透明度设置为0来隐藏元素。完全透明的元素将具有宽度。
缺点是元素仍会占用空间,但在所有情况下都不会成为问题。
例如:
$(img).css("opacity", 0) //element cannot be seen
width = $(img).width() //but has width
答案 8 :(得分:1)
这里大多数解决方案都忽略了最大的问题是,CSS的宽度通常会根据html中作用域的位置而改变。
如果我确定一个元素的offsetWidth是通过将它的一个克隆附加到body上,当它具有仅适用于当前范围的样式时,我会得到错误的宽度。
例如:
// CSS
.module-container .my-elem { 边框:60px纯黑色; }
现在,当我尝试在身体的背景下确定我的身高时,它会超出120px。你可以克隆模块容器,但你的JS不应该知道这些细节。
我还没有测试过它,但基本上Soul_Master的解决方案似乎是唯一可以正常工作的解决方案。但不幸的是,考虑到实施,使用起来可能成本高昂,而且性能也不好(因为这里提供的大多数解决方案都是如此。)
如果可能的话,请使用visibility:hidden。这仍然会渲染元素,让您无需大惊小怪地计算宽度。
答案 9 :(得分:0)
除了解决我的问题之后的the answer posted by Tim Banks,我还要编辑一个简单的事情。
其他人可能会遇到同样的问题;我在下拉列表中使用Bootstrap下拉列表。但是文本在这一点上可以更广泛地作为当前内容(并且通过css解决这个问题的方法并不多)。
我用过:
$table.css({ position: "absolute", visibility: "hidden", display: "table" });
相反,它将容器设置为一个表,如果内容较宽,该表总是按比例缩放。
答案 10 :(得分:0)
jQuery(".megamenu li.level0 .dropdown-container .sub-column ul .level1").on("mouseover", function () {
var sum = 0;
jQuery(this).find('ul li.level2').each(function(){
sum -= jQuery(this).height();
jQuery(this).parent('ul').css('margin-top', sum / 1.8);
console.log(sum);
});
});
悬停时,我们可以计算列表项的高度。
答案 11 :(得分:0)
如前所述,克隆和在其他地方附加方法不能保证相同的结果,因为样式可能有所不同。
下面是我的方法。它沿着父母走去寻找负责隐藏的父母,然后暂时取消隐藏它以计算所需的宽度,高度等。
var width = parseInt($image.width(), 10);
var height = parseInt($image.height(), 10);
if (width === 0) {
if ($image.css("display") === "none") {
$image.css("display", "block");
width = parseInt($image.width(), 10);
height = parseInt($image.height(), 10);
$image.css("display", "none");
}
else {
$image.parents().each(function () {
var $parent = $(this);
if ($parent.css("display") === "none") {
$parent.css("display", "block");
width = parseInt($image.width(), 10);
height = parseInt($image.height(), 10);
$parent.css("display", "none");
}
});
}
}