In the end, we solved this problem when we were working on the project. Record it as follows:
There are several situations:
1. Normal condition
<div style="width:500px; height:300px;">
<div id="div1" style="width:100%; height:100%; background-color:red;">
<div id="child" style="width:100%; height:100%; background-color:red; "></div>
</div>
</div>
$(function(){
console.log(document.getElementById("div1").scrollWidth); // 500
console.log(document.getElementById("div1").scrollHeight); // 300
console.log(document.getElementById("div1").offsetWidth); // 500
console.log(document.getElementById("div1").offsetHeight); // 500
console.log($("#div1").width()) // 500
console.log($("#div1").height()) // 300
console.log($("#child").width()) // 500
console.log($("#child").height()) // 300
})
2. Parent element display:none
<div style="width:500px; height:300px;display: none"><!-- Notice this is none -->
<div id="div1" style="width:100%; height:100%; background-color:red;">
<div id="child" style="width:100%; height:100%; background-color:red; "></div>
</div>
</div>
None of the above methods can be obtained
3. Parent element display:none, whose length and width are specific values
<div style="width:500px; height:300px;display: none">
<!-- Notice this is px -->
<div id="div1" style="width:100px; height:100px; background-color:red;">
<div id="child" style="width:100%; height:100%; background-color:red; "></div>
</div>
</div>
Output: 0 0 0 0 100 / / you can get the specific length and width 100 0 0
4. display:none, and width and height are specific values
<div style="width:500px; height:300px;">
<div id="div1" style="width:100px; height:100px; background-color:red;display: none">
<div id="child" style="width:100%; height:100%; background-color:red; "></div>
</div>
</div>
Output: 0 0 0 0 100 100 0 0
5. display:none, width height as a percentage (at this time, width() height() gets the width height of the browser)
<div style="width:500px; height:300px;">
<div id="div1" style="width:100%; height:100%; background-color:red;display: none">
<div id="child" style="width:100%; height:100%; background-color:red; "></div>
</div>
</div>
Output: 0 0 0 0 //Browser width and height 1920 640 0 0
To summarize, jquery's width() and height() methods are
When the parent element display:none, if the length and width of the child element are specific values, it can be obtained; if it is a percentage, it cannot be obtained. When the display of the parent element is not none, if the length and width of the child element are specific values, you can get it. When it is a percentage, you can get the length and width of the body
Then we need a solution. At this time, there is a jQuery plug-in. You can use jquery.actual.js to get the length and width of hidden elements
Source code:
;( function ( $ ){
$.fn.addBack = $.fn.addBack || $.fn.andSelf;
$.fn.extend({
actual : function ( method, options ){
// check if the jQuery method exist
if( !this[ method ]){
throw '$.actual => The jQuery method "' + method + '" you called does not exist';
}
var defaults = {
absolute : false,
clone : false,
includeMargin : false
};
var configs = $.extend( defaults, options );
var $target = this.eq( 0 );
var fix, restore;
if( configs.clone === true ){
fix = function (){
var style = 'position: absolute !important; top: -1000 !important; ';
// this is useful with css3pie
$target = $target.
clone().
attr( 'style', style ).
appendTo( 'body' );
};
restore = function (){
// remove DOM element after getting the width
$target.remove();
};
}else{
var tmp = [];
var style = '';
var $hidden;
fix = function (){
// get all hidden parents
$hidden = $target.parents().addBack().filter( ':hidden' );
style += 'visibility: hidden !important; display: block !important; ';
if( configs.absolute === true ) style += 'position: absolute !important; ';
// save the origin style props
// set the hidden el css to be got the actual value later
$hidden.each( function (){
var $this = $( this );
// Save original style. If no style was set, attr() returns undefined
tmp.push( $this.attr( 'style' ));
$this.attr( 'style', style );
});
};
restore = function (){
// restore origin style values
$hidden.each( function ( i ){
var $this = $( this );
var _tmp = tmp[ i ];
if( _tmp === undefined ){
$this.removeAttr( 'style' );
}else{
$this.attr( 'style', _tmp );
}
});
};
}
fix();
// get the actual value with user specific methed
// it can be 'width', 'height', 'outerWidth', 'innerWidth'... etc
// configs.includeMargin only works for 'outerWidth' and 'outerHeight'
var actual = /(outer)/.test( method ) ?
$target[ method ]( configs.includeMargin ) :
$target[ method ]();
restore();
// IMPORTANT, this plugin only return the value of the first element
return actual;
}
});
})( jQuery );
Usage:
$("#id").actual('height')
$("#id").actual('width')