获取 div 元素未溢出部分的高度

12

假设我有一个包装器(div),其上设置了overflow:hidden,并且内部有一个div,其高度远超过可见部分。如何获取内部div的可见高度?

<div id="wrapper" style="overflow: hidden; height:400px;">
    <div id="inner">
        <!--Lots of content in here-->
    </div>
<div>
每次尝试获取内部div的高度时,我尝试的每种方法都返回完整的高度,包括隐藏的部分,即2000px。我希望能够仅获取可见部分的高度,例如此示例中的400px。
我知道可以只获取parentNode的高度,但在生产环境中,内部div可能不是第一个子元素。因此,可能会有其他的div将它们分开,所以#inner的高度将是400减去它与#wrapper之间元素的偏移量。

嗯...我在考虑是否可以遍历 DOM 直到找到一个溢出隐藏标签。但其他人可能也有这个问题...我不知道。除非别人想出解决方案,否则我得绞尽脑汁。 - ryandlf
5个回答

7
作为基本算法,这个可以工作:
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;

但是如果你正在做这些事情,也许你已经在使用jQuery,并且它的.height().offset()函数可能会对你有所帮助:

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

使用window.getComputedStyle(node).height是一个不好的主意吗? - Kishore Relangi
@KishoreRelangi 首先,它无法处理溢出 http://jsfiddle.net/b5DGj/361/ - Zach Saucier

3
快速算法,向上遍历DOM树,查看window.getComputedStyle中的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
}

例子fiddle(查看您的控制台)。


1
注意,它不考虑滚动位置。 - Paul S.

1
我发现在各种情况下(包括溢出、使用了transform: translate(),以及元素和隐藏其溢出的元素之间存在其他嵌套容器的情况),唯一的方法是将.getBoundingClientRect()与隐藏元素溢出的祖先引用组合起来。
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)
        )
    }
}

演示

如果没有给出参考节点,则假定为父节点:演示

请注意,这不考虑元素是否可在视口中查看,仅考虑可见性(未因溢出而隐藏)。如果您需要两者,可以将功能与此答案结合使用。它还没有检查visibility: hidden,因此如果您需要检查节点及其所有祖先的style.visibility属性,则需要进行检查。


-1

我认为将一个兄弟元素放在它旁边,计算它的scrollTop和溢出元素的scrollTop,然后从兄弟元素的scrollTop中减去这个值可能会起作用。


这与滚动无关。 - Inanc Gumus

-1
下面的代码计算元素的可见部分。所谓可见部分是指在窗口中可见的部分,但我认为您可以轻松地将其改为基于任意容器元素进行计算。
function computeVisibleHeight ($t) {
        var top = $t.position().top;
        var windowHeight = $(window).height();
        var scrollTop = $(window).scrollTop();
        var height = $t.height();

        if (top < scrollTop && height - scrollTop >= windowHeight) {
            // first case: the top and the bottom of the element is outside of the window
            return windowHeight;
        } else if (top < scrollTop) {
            // second: the top is outside of the viewport but the bottom is visible
            return height - (scrollTop - top);
        } else if (top > scrollTop && top + height < windowHeight) {
            // the whole element is visible
            return height;
        } else {
            // the top is visible but the bottom is outside of the viewport
            return windowHeight - (top - scrollTop);
        }
    }

这段代码正在使用jQuery。


这不是问题的答案。该问题与视口无关。 - Inanc Gumus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接