如何查找未显示的元素的高度

时间:2011-11-18 18:03:01

标签: javascript html css

我正在编写一个网页,其中包含一个可以滑动打开和关闭的行的表格。最初,某些行已关闭(display: none),我希望它们可以滑动打开。设置高度并使用overflow: hidden对表格行不起作用,所以我正在更改表格内div的高度。

这很有效。唯一的问题是我需要知道div滑动之前的高度,这似乎是不可能的。我能想到的一个解决方案是加载带有行显示的页面,然后遍历它们,存储它们的高度并隐藏它们。我不喜欢这个解决方案,因为页面会在加载时跳转。

这是我的问题的一个简单,可运行的例子。

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
table, td {border: 1px solid black;}
#lower_row {display: none;}
#lower_div {overflow: hidden;}
</style>
<script type="text/javascript">
function toggleLower() {
    lowerRow = document.getElementById("lower_row");
    lowerDiv = document.getElementById("lower_div");
    if (getStyle(lowerRow, "display") == "none") {
        lowerRow.style.display = "table-row";
    }
    else {
        lowerRow.style.display = "none";
    }
    showHeight();
}
function showHeight() {
    lowerDiv = document.getElementById("lower_div");
    document.getElementById("info").innerHTML = getStyle(lowerDiv, "height");
}
// Return a style atribute of an element.
// J/S Pro Techniques p136
function getStyle(elem, name) {
    if (elem.style[name]) {
        return elem.style[name];
    }
    else if (elem.currentStyle) {
        return elem.currentStyle[name];
    }
    else if (document.defaultView && document.defaultView.getComputedStyle) {
        name = name.replace(/([A-Z])/g, "-$1");
        name = name.toLowerCase();
        s = document.defaultView.getComputedStyle(elem, "");
        return s && s.getPropertyValue(name);
    }
    else {
        return null;
    }
}
</script>
</head>

<body onload="showHeight()">
<p>The height the lower row is currently <span id="info"></span></p>
<table>
<tr id="upper_row" onclick="toggleLower()"><td><p>Click me to toggle the next row.</p></td></tr>
<tr id="lower_row"><td><div id="lower_div"><p>Peekaboo!</p></div></td></tr>
</table>

</body>
</html>

修改1:

一个建议的解决方案是将div移出页面。我不能让它工作,我认为它的高度会有所不同,因为它的高度取决于桌子的宽度。

我正在研究使用visibility:hidden的解决方案,但它有问题。它仍占用少量空间,报告的高度是错误的。以下是该解决方案的一个示例:

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
table {width: 250px;}
table, td {border: 1px solid black;}
#lower_row {position: absolute; visibility: hidden}
#lower_div {overflow: hidden;}
</style>
<script type="text/javascript">
function toggleLower() {
    lowerRow = document.getElementById("lower_row");
    lowerDiv = document.getElementById("lower_div");
    if (getStyle(lowerRow, "visibility") == "hidden") {
        lowerRow.style.visibility = "visible";
        lowerRow.style.position = "static";
    }
    else {
        lowerRow.style.visibility = "hidden";
        lowerRow.style.position = "absolute";
    }
    showHeight();
}
function showHeight() {
    lowerDiv = document.getElementById("lower_div");
    document.getElementById("info").innerHTML = getStyle(lowerDiv, "height");
}
// Return a style atribute of an element.
// J/S Pro Techniques p136
function getStyle(elem, name) {
    if (elem.style[name]) {
        return elem.style[name];
    }
    else if (elem.currentStyle) {
        return elem.currentStyle[name];
    }
    else if (document.defaultView && document.defaultView.getComputedStyle) {
        name = name.replace(/([A-Z])/g, "-$1");
        name = name.toLowerCase();
        s = document.defaultView.getComputedStyle(elem, "");
        return s && s.getPropertyValue(name);
    }
    else {
        return null;
    }
}
</script>
</head>

<body onload="showHeight()">
<p>The height the lower row is currently <span id="info"></span></p>
<table>
<tr id="upper_row" onclick="toggleLower()"><td><p>Click me to toggle the next row.</p></td></tr>
<tr id="lower_row"><td><div id="lower_div"><p>This is some long text. This is some long text. This is some long text. This is some long text.</p></div></td></tr>
</table>

</body>
</html>

编辑2:解决方案

保罗的回答是我的问题的解决方案:如何找到未显示的元素的高度。但是,它对我的​​问题不起作用。在我的网站上,div的高度取决于它的宽度,这取决于td的宽度,这取决于其他行的状态和表的宽度,这取决于页面的宽度。这意味着,即使我预先计算了高度,只要有人展开另一行或更改窗口大小,该值就会出错。此外,复制表并保持所有这些约束几乎是不可能的。

但是,我找到了解决方案。当用户单击以展开行时,我的网站将按顺序执行以下步骤:

  1. 将div.style.height设置为1px。
  2. 将row.style.display设置为table-row。
  3. 存储div.scrollHeight的值。
  4. 运行滚动动画,停在div.scrollHeight。
  5. 动画制作完成后,将div.style.height设置为auto。
  6. div.scrollHeight给出div的内容的高度,包括它的溢出。当div没有显示时它不起作用,但这对我的应用程序来说不是问题。这是代码的实例。 (同样,我没有包含滚动动画的代码,因为它太长了。)

    <!DOCTYPE HTML>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <style type="text/css">
    table, td {border: 1px solid black;}
    #lower_row {display: none;}
    #lower_div {overflow: hidden;}
    </style>
    <script type="text/javascript">
    function toggleLower() {
        var lowerRow = document.getElementById("lower_row");
        var lowerDiv = document.getElementById("lower_div");
        if (getStyle(lowerRow, "display") == "none") {
            lowerDiv.style.height = "0px";
            lowerRow.style.display = "table-row";
            showHeight();
            lowerDiv.style.height = "auto";
        }
        else {
            lowerDiv.style.height = "0px";
            showHeight();
            lowerRow.style.display = "none";
        }
    }
    function showHeight() {
        var lowerDiv = document.getElementById("lower_div");
        document.getElementById("info").innerHTML = lowerDiv.scrollHeight;
    }
    // Return a style atribute of an element.
    // J/S Pro Techniques p136
    function getStyle(elem, name) {
        if (elem.style[name]) {
            return elem.style[name];
        }
        else if (elem.currentStyle) {
            return elem.currentStyle[name];
        }
        else if (document.defaultView && document.defaultView.getComputedStyle) {
            name = name.replace(/([A-Z])/g, "-$1");
            name = name.toLowerCase();
            s = document.defaultView.getComputedStyle(elem, "");
            return s && s.getPropertyValue(name);
        }
        else {
            return null;
        }
    }
    </script>
    </head>
    
    <body>
    <p>The height the lower row is currently <span id="info">...</span></p>
    <table>
    <tr id="upper_row" onclick="toggleLower()"><td><p>Click me to toggle the next row.</p></td></tr>
    <tr id="lower_row"><td><div id="lower_div"><p>
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    This is some long text. This is some long text. This is some long text. This is some long text.
    </p></div></td></tr>
    </table>
    
    </body>
    </html>
    

    2 个答案:

    答案 0 :(得分:14)

    您可以使用内容复制div并将其放在具有绝对定位top:-10000; left:-10000;的正文中,使其位于可见区域之外,然后您可以计算高度并从DOM中删除克隆。

    <强>更新

    或者,如果您以动态方式添加元素,可以将其设置为display:blockposition:absolutevisibility:hidden - 但您必须确保它不会更改页面上任何元素的位置。 visibility:hidden - 不显示元素,但会计算其尺寸(与display: none形成对比)

    <强>更新

    在您的特定情况下,您的父母会对孩子的尺寸产生影响,因此您需要将您的元素克隆到可见区域之外的“相似”父级。通过说“相似”,我的意思是它应该具有相同的尺寸,但一般来说 - 样式和所有与它的尺寸相关的东西:

    var wrapper = $('<div></div>').appendTo('body').css('display', 'block').css('position', 'absolute').css('top', -10000).css('left', -10000).css('width', $('table').css('width'));
    var clone = $('#lower_div').clone().appendTo(wrapper);    
    document.getElementById("info").innerHTML = clone.height();
    

    以下是您的工作jsfiddle

    答案 1 :(得分:0)

    您可以通过显示元素、捕获高度,然后在浏览器重新绘制屏幕之前重新隐藏元素来完成此操作。因此,用户永远不会注意到发生的任何事情。我为用于滑动具有动态高度的打开和关闭元素的包装执行此操作:

    https://github.com/alexmacarthur/slide-element/blob/master/src/index.ts

    在超级简单的代码中:

    <div id="element" style="display: none;">hello</div>
    
    <script>
       const element = document.getElementById('element');
       
       element.style.display = "";
       const elementHeight = element.clientHeight;
       element.style.display = "none";
    
       console.log(elementHeight); // whatever the rendered height is.
    </script>