Get height of non-overflowed portion of div

13,363

Solution 1

As basic algorithm this could work:

var offset = 0;
var node = document.getElementById("inner");
while (node.offsetParent && node.offsetParent.id != "wrapper")
{
    offset += node.offsetTop;
    node = node.offsetParent;
}
var visible = node.offsetHeight - offset;

But if you're doing these kinds of things, maybe you already use jQuery, which might be of service with its .height() and .offset() functions:

$("#wrapper").height()-
$("#inner").offset()['top']+
$("#wrapper").offset()['top'];  

Solution 2

Quick algorithm that goes up the DOM tree looking at window.getComputedStyle for overflow: hidden

function visibleArea(node){
    var o = {height: node.offsetHeight, width: node.offsetWidth}, // size
        d = {y: (node.offsetTop || 0), x: (node.offsetLeft || 0), node: node.offsetParent}, // position
        css, y, x;
    while( null !== (node = node.parentNode) ){  // loop up through DOM
        css = window.getComputedStyle(node);
        if( css && css.overflow === 'hidden' ){  // if has style && overflow
            y = node.offsetHeight - d.y;         // calculate visible y
            x = node.offsetWidth - d.x;          // and x
            if( node !== d.node ){
                y = y + (node.offsetTop || 0);   // using || 0 in case it doesn't have an offsetParent
                x = x + (node.offsetLeft || 0);
            }
            if( y < o.height ) {
                if( y < 0 ) o.height = 0;
                else o.height = y;
            }
            if( x < o.width ) {
                if( x < 0 ) o.width = 0;
                else o.width = x;
            }
            return o;                            // return (modify if you want to loop up again)
        }
        if( node === d.node ){                   // update offsets
            d.y = d.y + (node.offsetTop || 0);
            d.x = d.x + (node.offsetLeft || 0);
            d.node = node.offsetParent;
        }
    }
    return o;                                    // return if no hidden
}

example fiddle (look at your console).

Solution 3

The only way I've found to do this in every circumstance, including when there's overflow, transform: translate()s are used, and there are other nested containers in between an element and the element that's hiding its overflow is to combine .getBoundingClientRect() with a reference to the ancestor that's hiding the element's overflow:

function getVisibleDimensions(node, referenceNode) {
    referenceNode = referenceNode || node.parentNode;

    var pos = node.getBoundingClientRect();
    var referencePos = referenceNode.getBoundingClientRect();

    return {
        "width": Math.min(
            node.clientWidth,
            referencePos.left + referenceNode.clientWidth - pos.left, 
            node.clientWidth - (referencePos.left - pos.left)
        ),
        "height": Math.min(
            node.clientHeight, 
            referencePos.top + referenceNode.clientHeight - pos.top,
            node.clientHeight - (referencePos.top - pos.top)
        )
    }
}

Demo.

If a reference node is not given, the parent node is assumed: Demo.

Note that this doesn't take into account whether or not an element is viewable in the viewport, just visible (not hidden due to overflow). If you need both, you can combine functionality with this answer. It also has no check of visibility: hidden, so if you need that you need to check the style.visibility property of the node and all its ancestors.

Share:
13,363
ryandlf
Author by

ryandlf

Updated on July 20, 2022

Comments

  • ryandlf
    ryandlf almost 2 years

    Say I have a wrapper div with a overflow:hidden on it and a div inside that that spans far below the visible portion. How can I get the visible height of the internal div?

    <div id="wrapper" style="overflow: hidden; height:400px;">
        <div id="inner">
            <!--Lots of content in here-->
        </div>
    <div>
    

    Every method I try attempting to get the height of the inner div returns the complete height including the hidden parts, i.e. 2000px. I want to be able to get the height of only the visible portion, so 400px in this example case.

    I know I could just get the height of the parentNode, but in production, the inner div might not be a first child. So there might be other divs separating them, and so the height of #inner would be 400 - whatever the offsets of the elements between it and #wrapper.

  • Paul S.
    Paul S. over 11 years
    Note, it doesn't take into account the scroll location.
  • Inanc Gumus
    Inanc Gumus over 8 years
    This is not the answer to the question. Question does not deal with the viewport.
  • Inanc Gumus
    Inanc Gumus over 8 years
    This is nothing to do with scrolling.
  • Kishore Relangi
    Kishore Relangi almost 8 years
    is it bad idea to use window.getComputedStyle(node).height
  • Zach Saucier
    Zach Saucier over 7 years
    @KishoreRelangi For one, it doesn't work with overflow jsfiddle.net/b5DGj/361