jQuery - 不可见时获取元素的宽度(显示:无)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1472303/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery - Get Width of Element when Not Visible (Display: None)
提问by Martin
It seems like in jQuery when an element is not visible width() returns 0. Makes sense, but I need to get the width of a table in order to set the width of the parent before I show the parent.
当元素不可见时,似乎在 jQuery 中 width() 返回 0。有道理,但我需要获取表格的宽度,以便在显示父级之前设置父级的宽度。
As noted below, there is text in the parent, that makes the parent skew and look nasty. I want the parent to be only as wide as the table and have the text wrap.
如下所述,父级中有文本,这使父级倾斜并看起来令人讨厌。我希望父级的宽度与表格一样宽,并且文本换行。
<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:
CSS:
#parent
{
display: none;
}
Javascript:
Javascript:
var tableWidth = $('#parent').children('table').outerWidth();
if (tableWidth > $('#parent').width())
{
$('#parent').width(tableWidth);
}
tableWidth always returns 0 since it is not visible (is my guess since it gives me a number when visible). Is there a way to get the width of the table without making the parent visible?
tableWidth 总是返回 0,因为它不可见(这是我的猜测,因为它在可见时给了我一个数字)。有没有办法在不使父级可见的情况下获得表格的宽度?
采纳答案by Tim Banks
Here is a trick I have used. It involves adding some CSS properties to make jQuery think the element is visible, but in fact it is still hidden.
这是我使用过的一个技巧。它涉及添加一些 CSS 属性,使 jQuery 认为该元素是可见的,但实际上它仍然是隐藏的。
var $table = $("#parent").children("table");
$table.css({ position: "absolute", visibility: "hidden", display: "block" });
var tableWidth = $table.outerWidth();
$table.css({ position: "", visibility: "", display: "" });
It is kind of a hack, but it seems to work fine for me.
这有点像黑客,但对我来说似乎很好用。
UPDATE
更新
I have since written a blog postthat covers this topic. The method used above has the potential to be problematic since you are resetting the CSS properties to empty values. What if they had values previously? The updated solution uses the swap() method that was found in the jQuery source code.
从那以后,我写了一篇涵盖这个主题的博客文章。由于您将 CSS 属性重置为空值,因此上面使用的方法可能会出现问题。如果它们以前有值怎么办?更新后的解决方案使用了 jQuery 源代码中的 swap() 方法。
Code from referenced blog post:
来自参考博客文章的代码:
//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));
回答by Fábio Paiva
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"));
回答by Marco Kerwitz
Based on Roberts answer, here is my function. This works for me if the element or its parent have been faded out via jQuery, can either get inner or outer dimensions and also returns the offset values.
根据罗伯茨的回答,这是我的功能。如果元素或其父元素已通过 jQuery 淡出,这对我有用,可以获取内部或外部尺寸并返回偏移值。
/edit1: rewrote the function. it's now smaller and can be called directly on the object
/edit1:重写函数。它现在更小,可以直接在对象上调用
/edit2: the function will now insert the clone just after the original element instead of the body, making it possible for the clone to maintain inherited dimensions.
/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();
回答by Soul_Master
I try to find working function for hidden element but I realize that CSS is much complex than everyone think. There are a lot of new layout techniques in CSS3 that might not work for all previous answers like flexible box, grid, column or even element inside complex parent element.
我试图找到隐藏元素的工作功能,但我意识到 CSS 比每个人想象的都要复杂。CSS3 中有很多新的布局技术可能不适用于所有以前的答案,例如灵活的框、网格、列甚至复杂父元素中的元素。
flexibox example
弹性盒示例
I think the only sustainable & simple solution is real-time rendering. At that time, browser should give you that correct element size.
我认为唯一可持续且简单的解决方案是实时渲染。那时,浏览器应该给你正确的元素大小。
Sadly, JavaScript does not provide any direct event to notify when element is showed or hidden. However, I create some function based on DOM Attribute Modified API that will execute callback function when visibility of element is changed.
遗憾的是,JavaScript 没有提供任何直接事件来通知元素何时显示或隐藏。但是,我创建了一些基于 DOM 属性修改 API 的函数,该函数将在元素可见性改变时执行回调函数。
$('[selector]').onVisibleChanged(function(e, isVisible)
{
var realWidth = $('[selector]').width();
var realHeight = $('[selector]').height();
// render or adjust something
});
For more information, Please visit at my project GitHub.
有关更多信息,请访问我的项目 GitHub。
https://github.com/Soul-Master/visible.event.js
https://github.com/Soul-Master/visible.event.js
回答by Robert
Thank you for posting the realWidth function above, it really helped me. Based on "realWidth" function above, I wrote, a CSS reset, (reason described below).
感谢您发布上面的 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" gets the width of an existing tag. I tested this with some image tags. The problem was, when the image has given CSS dimension per width (or max-width), you will never get the real dimension of that image. Perhaps, the img has "max-width: 100%", the "realWidth" function clone it and append it to the body. If the original size of the image is bigger than the body, then you get the size of the body and not the real size of that image.
"realWidth" 获取现有标签的宽度。我用一些图像标签对此进行了测试。问题是,当图像为每个宽度(或最大宽度)指定 CSS 尺寸时,您将永远无法获得该图像的真实尺寸。也许,img 具有“max-width: 100%”,“realWidth”函数将其克隆并将其附加到主体。如果图像的原始尺寸大于身体,那么您将获得身体的尺寸,而不是该图像的实际尺寸。
回答by rannmann
If you need the width of something that's hidden and you can't un-hide it for whatever reason, you can clone it, change the CSS so it displays off the page, make it invisible, and then measure it. The user will be none the wiser if it's hidden and deleted afterwards.
如果您需要隐藏某些东西的宽度并且无论出于何种原因都无法取消隐藏它,您可以克隆它,更改 CSS 使其显示在页面之外,使其不可见,然后测量它。如果它被隐藏并随后被删除,用户将不会更聪明。
Some of the other answers here just make the visibility hidden which works, but it will take up a blank spot on your page for a fraction of a second.
这里的其他一些答案只是隐藏了可见性,但它会在您的页面上占据一个空白点几分之一秒。
Example:
例子:
$itemClone = $('.hidden-item').clone().css({
'visibility': 'hidden',
'position': 'absolute',
'z-index': '-99999',
'left': '99999999px',
'top': '0px'
}).appendTo('body');
var width = $itemClone.width();
$itemClone.remove();
回答by Jake
One solution, though it won't work in all situations, is to hide the element by setting the opacity to 0. A completely transparent element will have width.
一种解决方案,尽管它不适用于所有情况,但通过将不透明度设置为 0 来隐藏元素。完全透明的元素将具有宽度。
The draw back is that the element will still take up space, but that won't be an issue in all cases.
缺点是元素仍会占用空间,但这并不是所有情况下的问题。
For example:
例如:
$(img).css("opacity", 0) //element cannot be seen
width = $(img).width() //but has width
回答by sourcecode
Before take the width make the parent display show ,then take the width and finally make the parent display hide. Just like following
在取宽度之前让父显示显示,然后取宽度,最后使父显示隐藏。就像跟随
$('#parent').show();
var tableWidth = $('#parent').children('table').outerWidth();
$('#parent').hide();
if (tableWidth > $('#parent').width())
{
$('#parent').width() = tableWidth;
}
回答by Code Novitiate
The biggest issue being missed by most solutions here is that an element's width is often changed by CSS based on where it is scoped in html.
此处大多数解决方案忽略的最大问题是,CSS 经常根据元素在 html 中的作用域位置来更改元素的宽度。
If I was to determine offsetWidth of an element by appending a clone of it to body when it has styles that only apply in its current scope I would get the wrong width.
如果我要通过将元素的副本附加到 body 来确定元素的 offsetWidth,当它具有仅适用于其当前范围的样式时,我会得到错误的宽度。
for example:
例如:
//css
//css
.module-container .my-elem{ border: 60px solid black; }
.module-container .my-elem{ 边框:60px 纯黑色;}
now when I try to determine my-elem's width in context of body it will be out by 120px. You could clone the module container instead, but your JS shouldn't have to know these details.
现在,当我尝试在 body 上下文中确定 my-elem 的宽度时,它将超出 120 像素。您可以改为克隆模块容器,但您的 JS 不必知道这些细节。
I haven't tested it but essentially Soul_Master's solution appears to be the only one that could work properly. But unfortunately looking at the implementation it will likely be costly to use and bad for performance (as most of the solutions presented here are as well.)
我还没有测试过,但基本上 Soul_Master 的解决方案似乎是唯一可以正常工作的解决方案。但不幸的是,从实现来看,它的使用成本可能很高,而且对性能不利(因为这里介绍的大多数解决方案也是如此。)
If at all possible then use visibility: hidden instead. This will still render the element, allowing you to calculate width without all the fuss.
如果可能,请改用可见性:隐藏。这仍然会渲染元素,让您可以毫不费力地计算宽度。
回答by Mathijs Segers
In addition to the answer posted by Tim Banks, which followed to solving my issue I had to edit one simple thing.
除了Tim Banks 发布的答案之外,为了解决我的问题,我还必须编辑一件简单的事情。
Someone else might have the same issue; I'm working with a Bootstrap dropdown in a dropdown. But the text can be wider as the current content at this point (and there aren't many good ways to resolve that through css).
其他人可能有同样的问题;我正在使用下拉菜单中的 Bootstrap 下拉菜单。但是此时文本可以比当前内容更宽(并且通过 css 解决这个问题的好方法并不多)。
I used:
我用了:
$table.css({ position: "absolute", visibility: "hidden", display: "table" });
instead, which sets the container to a table which always scales in width if the contents are wider.
相反,它将容器设置为一个表格,如果内容更宽,则该表格的宽度总是缩放。