jQuery – 当不可见时获取元素的宽度(显示:无)
它看起来像在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,因为它不可见(是我的猜测,因为它给了我一个数字,当可见)。 有没有办法获得表的宽度,而不使父母可见?
这是我用过的一个技巧。 它涉及到添加一些CSS属性,使jQuery认为元素是可见的,但实际上它仍然是隐藏的。
var $table = $("#parent").children("table"); $table.css({ position: "absolute", visibility: "hidden", display: "block" }); var tableWidth = $table.outerWidth(); $table.css({ position: "", visibility: "", display: "" });
这是一种黑客,但似乎对我工作得很好。
UPDATE
我已经写了一篇博客文章 ,涵盖了这个主题。 上面使用的方法可能会有问题,因为您将CSS属性重置为空值。 如果他们以前有价值呢? 更新的解决scheme使用在jQuery源代码中find的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));
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"));
根据罗伯茨的回答,这里是我的function。 这适用于我,如果元素或它的父母已经通过jQuery淡出,可以得到内部或外部的维度,也返回偏移值。
/ edit1:重写了这个函数。 它现在变小了,可以直接在对象上调用
/ edit2:函数现在将克隆插入原始元素而不是正文后面,从而使克隆可以维护inheritance的维度。
$.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();
感谢您发布上面的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”获取现有标签的宽度。 我用一些图片标签testing了这个。 问题是,当图像给每个宽度(或最大宽度)的CSS尺寸,你永远不会得到该图像的真实维度。 也许,img有“最大宽度:100%”,“realWidth”函数克隆它并将其附加到主体。 如果图像的原始大小比身体大,那么您将获得身体的大小,而不是该图像的实际大小。
我试图find隐藏元素的工作function,但是我意识到CSS比每个人都想象的要复杂得多。 在CSS3中有很多新的布局技术,可能不适用于所有以前的答案,如灵活的框,网格,列,甚至复杂的父元素内的元素。
flexibox例子
我认为唯一可持续和简单的解决scheme是实时渲染 。 那时,浏览器应该给你正确的元素大小 。
不幸的是,当元素被显示或隐藏时,JavaScript不提供任何直接事件来通知。 但是,我创build了一些基于DOM Attribute Modified API的函数,当元素的可见性发生变化时,它将执行callback函数。
$('[selector]').onVisibleChanged(function(e, isVisible) { var realWidth = $('[selector]').width(); var realHeight = $('[selector]').height(); // render or adjust something });
有关更多信息,请访问我的项目GitHub。
Soul-Master/visible.event.html
演示: http : //jsbin.com/ETiGIre/7
如果您需要隐藏的东西的宽度,并且无论出于何种原因都无法将其隐藏,则可以将其克隆,更改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();
在取得宽度之前,先显示父屏幕,然后取宽度,最后隐藏父屏幕。 就像下面
$('#parent').show(); var tableWidth = $('#parent').children('table').outerWidth(); $('#parent').hide(); if (tableWidth > $('#parent').width()) { $('#parent').width() = tableWidth; }
这里大多数解决scheme所遗漏的最大的问题是,元素的宽度通常由CSS根据在html中作用域的位置而改变。
如果我通过将它的克隆附加到body来确定一个元素的offsetWidth,那么它的样式只适用于它的当前范围,我会得到错误的宽度。
例如:
// CSS
.module-container .my-elem {border:60px纯黑色; }
现在当我试图确定我的elem的宽度在身体上下文将是120px。 你可以克隆模块容器,但是你的JS不需要知道这些细节。
我还没有testing过,但基本上Soul_Master的解决scheme似乎是唯一可以正常工作的解决scheme。 但不幸的是,在实施过程中,使用成本可能很高,性能也不好(因为这里介绍的大多数解决scheme都是这样)。
如果可能的话使用可见性:隐藏。 这将仍然渲染元素,让您计算宽度没有所有的大惊小怪。
一种解决scheme,尽pipe它不能在所有情况下工作,但是通过将不透明度设置为0来隐藏元素。完全透明的元素将具有宽度。
缺点是元素仍然会占用空间,但这不是所有情况下的问题。
例如:
$(img).css("opacity", 0) //element cannot be seen width = $(img).width() //but has width
除了Tim Banks发布的解决我的问题之外,我不得不编辑一个简单的东西。
其他人可能有同样的问题; 我正在使用下拉菜单中的Bootstrap下拉菜单。 但是,文本可以更广泛的当前内容在这一点上(并没有很多好的方法来解决,通过CSS)。
我用了:
$table.css({ position: "absolute", visibility: "hidden", display: "table" });
相反,如果内容较宽,则将容器设置为总是按比例缩放的表格。