On how to get the width and height of display:none

Keywords: JQuery

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')

Every step is worth a thousand miles

Posted by FillePille on Tue, 31 Mar 2020 15:22:41 -0700