2009-09-24 71 views
101

看起來像在jQuery中當元素不可見時width()返回0.有意義,但我需要獲取表格的寬度以便在顯示父級之前設置父級的寬度。jQuery - 當不可見時獲取元素的寬度(顯示:無)

如下所述,父母中有文字,使父母歪斜,看起來很討厭。我希望父級只能和表一樣寬,並且有文本換行。

<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,因爲它是不可見的(是我的猜想,因爲它給了我一個號碼時可見)。有沒有辦法獲得表的寬度,而不使父母可見?

回答

89

這是我用過的一個技巧。它涉及到添加一些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屬性重置爲空值。如果他們以前有價值會怎麼樣?更新後的解決方案使用在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)); 
+0

,完美的工作,謝謝! – Martin 2009-09-24 22:50:17

+1

這不會讓瀏覽器重畫兩次頁面嗎?如果是這樣,這是一個不太理想的解決方案。 – marcusklaas 2011-06-25 21:18:52

+0

@Tim銀行非常好!我其實寫了一個類似的擴展名。我一直注意到** Firefox **中很奇怪的行爲,width()返回0,你和我的插件都是。最重要的是,它永遠不會影響填充。 http://jsfiddle.net/67cgB/。我正在最困難的時候弄清楚還有什麼可以解決的。 – 2013-02-14 16:32:25

38
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")); 
+0

髒好招!確保克隆具有正確的css屬性(例如,如果原始元素的字體大小爲15,則應使用clone.css(「visibility」,「hidden」)。css(「font-size」,「15px」 );) – alex 2012-12-19 22:27:26

+13

只需指出,如果你的元素從任何父類繼承了它的寬度,這將不起作用。它只會繼承不正確的身體寬度。 – Dean 2013-03-05 11:32:30

+2

我修改了'clone.css(「visibility」,「hidden」);'clone to clone.css({「visibility」:「hidden」,「display」:「table」});'這就解決了問題由@Dean – isapir 2015-04-30 15:17:02

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具有「最大寬度:100%」,「realWidth」函數克隆它並將其附加到主體。 如果圖像的原始大小比身體大,那麼您將獲得身體的大小,而不是該圖像的實際大小。

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(); 
+0

YUI版本適用於那些需要它的人:https://gist.github。COM/samueljseay/13c2e69508563b2f0458 – 2014-06-04 00:02:21

+0

的offsetTop是糾正因爲它是克隆,而不是「真實」項目的項目?如果您使用$ this.offset()。頂部?另外,好奇的你用的是什麼頂/離開?我只使用「寬度」,但不知道我是否應該關注這些偏移出於某種原因。 – Terry 2016-03-28 13:50:30

0

除了the answer posted by Tim Banks,隨着解決我的問題,我不得不編輯一件簡單的事情。

別人可能有同樣的問題;我在下拉菜單中使用Bootstrap下拉菜單。但是,文本可能會更廣泛,因爲在這一點上當前的內容(並沒有很多好的方法來解決這個問題)。

我使用:

$table.css({ position: "absolute", visibility: "hidden", display: "table" }); 

代替,其中容器設置爲總是在寬度縮放如果內容是寬的表。

3

我試圖找到隱藏的元素工作的功能,但我知道CSS是非常複雜的比任何人想象。 CSS3中有許多新的佈局技術,可能不適用於所有以前的答案,如靈活的框,網格,列或甚至複雜父元素中的元素。

flexibox例如 enter image description here

我認爲唯一可持續的&簡單的辦法就是實時渲染。那時候,瀏覽器應該會給你那個正確的元素大小

可悲的是,JavaScript並沒有提供任何直接的事件,當元素被顯示或隱藏的通知。但是,我創建了一些基於DOM Attribute Modified API的函數,當元素的可見性發生變化時,它將執行回調函數。

$('[selector]').onVisibleChanged(function(e, isVisible) 
{ 
    var realWidth = $('[selector]').width(); 
    var realHeight = $('[selector]').height(); 

    // render or adjust something 
}); 

欲瞭解更多信息,請在我的項目GitHub上參觀。

https://github.com/Soul-Master/visible.event.js

演示:http://jsbin.com/ETiGIre/7

+4

** CSS是非常複雜的比任何人想** 這是如此的真實... – dgellow 2014-03-20 16:36:09

1

之前採取的寬度使父顯示節目,然後採取寬,最終使父顯示隱藏。就像下面

$('#parent').show(); 
var tableWidth = $('#parent').children('table').outerWidth(); 
$('#parent').hide(); 
if (tableWidth > $('#parent').width()) 
{ 
    $('#parent').width() = tableWidth; 
} 
1

最大的問題大部分解決方案被錯過這裏是一個元素的寬度由CSS基於它在HTML中的作用範圍經常改變。

如果我是通過追加它的克隆體時,它的風格,只有在其目前的適用範圍,我會得到錯誤的寬度來確定元素的offsetWidth。

例如:

// CSS

.module容器。我-ELEM { 邊界:60像素實心黑色; }

現在,當我試圖確定在體內的情況下,將120像素成爲了我:馬的寬度。你可以克隆模塊容器,但是你的JS不需要知道這些細節。

我沒有測試過,但本質上Soul_Master的解決方案似乎是唯一的,可以正常工作的一個。但不幸的是看它的實施將可能是昂貴的使用和不好的表現

如果可能的話,然後使用可見性(因爲大多數這裏介紹的解決方案都是爲好。):隱藏代替。這仍然會渲染元素,讓您無需大驚小怪地計算寬度。

0

的一個解決方案,但它不會在所有情況下工作,是不透明度設置爲0甲完全透明的元件將具有寬度隱藏元件。

的拉回是元素仍然會佔用空間,但不會在所有情況下的問題。

例如:

$(img).css("opacity", 0) //element cannot be seen 
width = $(img).width() //but has width 
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(); 
+1

如果元件尺寸由父容器或更復雜的CSS選擇器的影響,基於佈局層次它將無法工作。 – 2017-02-20 08:39:29