29

Why I am getting Element offsetHeight "0"? even element original height is not showing

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style>
/* Added for Menu    */
.navbar
{
  list-style: none;`enter code here`
  padding: 0 10px;
  margin: 0;
  float: left;
  width: 980px;
  background: url(images/navbar.gif) repeat-x;
}
.navbar ul
{
 list-style: none;
  padding: 0px;
  margin: 0;
  float: left;
  width: 260px;
}
.navbar ul li
{
    float:left;
    position:relative;
    z-index:1000;
    margin:0px;
    padding:0px;
}
.navbar ul li ul
{
    display:none;
    border:none;
    width: 260px;
    padding:0 0px 0px 0px;
}
.navbar ul li a
{
     font-size: 12px;
     float:left;
     display:block;
     line-height:3.1em;
     padding:0 16px 0 16px;
     text-decoration:none;
     color:#FFF;
}
.navbar ul li:hover
{
    width:auto;
}
.navbar ul li:hover a
{
    background:url(images/navbar_subnav.png)  repeat-x scroll 0 0 transparent;          text-decoration:none;
}
.navbar ul li:hover ul
{
    display:block;
    position:absolute;
    z-index:998;
    top:0px;
    margin-top:25px;
    left:0;
}
.navbar ul li:hover ul li ul
{
    background-position: center bottombottom;
    cursor: pointer;
}
.navbar ul li:hover ul li a
{
    display:block;
    line-height:1.3em;
    padding:4px 16px 4px 16px;
    border-bottom:1px solid #205284;
    border-left:1px solid #205284;
    border-right:1px solid #205284;
    border-top:1px solid #205284;
    z-index: 10000;
    width:200px;
  }
.navbar ul li:hover ul li a:hover
{
     background-color:#000;
     text-decoration:underline;
     color: #0099FF;
     cursor: hand;

}
.navbar ul li a:hover ul
{
    display:block;
    position:absolute;
    z-index: 998;
    top:3.1em;
    t\op:3.0em;
    left:0;
    marg\in-top:0.1em;
}
.navbar ul li a:hover ul li a
 {
    display:block;
    height:1px;
    line-height:1.3em;
    padding:4px 16px 4px 16px;
    background-color:#000;
    font-weight:normal;
    color:#FFF;
}
.navbar ul li a:hover ul li a ul
{
    visibility:hidden;
    height:0px;
    width:0px;
    position:absolute;
    z-index: 997;
}
.navbar ul li a:hover ul li a:hover
{
    background-color:#000;
    text-decoration:underline;
}

</style>
</head>

<body>
<div class="navbar">
<ul>
            <li>
                <a href="#">menu item 1</a>
                <ul style="top:0px" >
                    <li style="width:288px;"><center><a href="#" onmouseover="movedown()" onmouseout="stopscroll()"><img src="images/menu-arrow-down.png" width="8" height="6"   alt="Down"></a></center></li>
<script> //<![CDATA[
var speed=2
iens6=document.all||document.getElementById
ns4=document.layers
if (iens6){
document.write('<div id="container" style="position:relative;width:310px;height:165px;overflow:hidden;border:0px solid #205284">')
document.write('<div id="content" style="position:absolute;width:290px;left:0px;top:-1px;">')
}
//]]></script>
<ilayer name="nscontainer" width="190">
<layer name="nscontent" width="290" height="155" visibility="hidden">
                    <li style="top:-1px;"><a href="#">sub menu item 1  menu item 1</a></li>
                    <li style="top:-1px;"><a href="#">sub menu item 2  menu item 1</a></li>                    <li style="top:-1px;"><a href="#">sub menu item 3</a></li>
                    <li style="top:-1px;"><a href="#">sub menu item 1</a></li>
                    <li style="top:-1px;"><a href="#">sub menu item 1</a></li>
                    <li style="top:-1px;"><a href="#">sub menu item 2</a></li>              
                    <li style="top:-1px;"><a href="#">sub menu item 3</a></li>
                    <li style="top:-1px;"><a href="#">sub menu item 1</a></li>
                    <li style="top:-1px;"><a href="#">sub menu </a></li>
                    <li style="top:-1px;"><a href="#">sub menu </a></li>
                    <li style="top:-1px;"><a href="#">sub menu </a></li>
                    <li style="top:-1px;"><a href="#">sub menu </a></li>              
                    <li style="top:-1px;"><a href="#">sub menu </a></li>
                    <li style="top:-1px;"><a href="#">sub menu</a></li>

</layer>
</ilayer>
<script> //<![CDATA[
if (iens6)
{
document.write('</div></div>')
var crossobj=document.getElementById? document.getElementById('content') : document.all.content
//alert("document.getElementById('content').offsetHeight :"+ document.getElementById('content').offsetHeight);
alert("crossobj.prototype.outerHeight" + crossobj.prototype.outerHeight);
var contentheight=crossobj.offsetHeight
//var contentheight=document.getElementById('content').style.height;
//alert("ContentHeight :"+contentheight);
}
else if (ns4)
{
    var crossobj=document.nscontainer.document.nscontent
    var contentheight=crossobj.clip.height
}
function movedown(){
if (window.moveupvar) clearTimeout(moveupvar)
{
    if (iens6&&parseInt(crossobj.style.top)>=(contentheight*(-1)+100))
    {
        crossobj.style.top=parseInt(crossobj.style.top)-speed+"px"
    }
    else if(ns4&&crossobj.top>=(contentheight*(-1)+100))
    {
        crossobj.top-=speed
    }
    /*else
    {
        crossobj.style.top=parseInt(crossobj.style.top)-speed+"px"
    }*/
}
    movedownvar=setTimeout("movedown()",20)
}
function moveup()
{
    if (window.movedownvar) clearTimeout(movedownvar)
    {
        if (iens6&&parseInt(crossobj.style.top)<=0)
        {
        crossobj.style.top=parseInt(crossobj.style.top)+speed+"px"
        }
        else if (ns4&&crossobj.top<=0)
        {
        crossobj.top+=speed
        }
        moveupvar=setTimeout("moveup()",20)
    }
}
function getcontent_height()
{
    if (iens6)
    {
        //alert("getcontent_height : "+document.getElementById("content").style.height);
        //contentheight=document.getElementById("content").style.height;
        contentheight=crossobj.offsetHeight
    }
    else if (ns4)
    {
        document.nscontainer.document.nscontent.visibility="show"
    }
}
window.onload=getcontent_height;
//]]></script>
                    <li><center><a href="#" onmouseover="moveup()" onmouseout="stopscroll()"><img src="images/menu-arrow-down.png" width="8" height="6" alt="Down"></a> </center></li>
                </ul>
            </li>
           </ul> 
      </div>    
</body>
</html>
Kamyar Infinity
  • 2,711
  • 1
  • 21
  • 32
kumarjcet
  • 419
  • 1
  • 5
  • 8

5 Answers5

22

Sometimes offsetHeight will return zero because the element you've created has not been rendered in the Dom yet. I wrote this function for such circumstances:

function getHeight(element)
{
    element.style.visibility = "hidden";
    document.body.appendChild(element);
    var height = element.offsetHeight + 0;
    document.body.removeChild(element);
    element.style.visibility = "visible";
    return height;
}
Lonnie Best
  • 9,936
  • 10
  • 57
  • 97
  • 5
    I had an issue with the element disappearing from its original place. Adding `element = element.cloneNode(true);` to the top of the function fixed it. – Sámal Rasmussen May 09 '17 at 10:29
  • what do you do when this is happening to the body? – merhoo Mar 31 '20 at 01:37
  • 1
    @merhoo You wouldn't use the function above. Are you saying that `document.body.offsetHeight` equals "0"? Is this measurement performed before or after the [load event](https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event)? Are all of the dynamically appended contents of body (if any) rendered yet? Does the body's content solely contain absolutely positioned elements? – Lonnie Best Apr 01 '20 at 06:55
14

You are trying to get offsetHeight of a hidden element. the css .navbar ul li ul has display:none that would make all of it's content invisible, including crossobj and you can't get height of elements that are not displayed, their height is simply put 0.

Kamyar Infinity
  • 2,711
  • 1
  • 21
  • 32
  • hi Thanks for ur reply.... based on that only menu over its dispalying submenu if i remove that mean by default its showing menu and submenu... can u help me to prevent this... – kumarjcet Aug 04 '11 at 09:50
  • there's a trick for this problem that you can position your tag around -1000px -1000px instead of using `display:none`, and then use `offsetHeight` to measure the height, and instead of changing display you'll need to change the position to make the tag visible – Kamyar Infinity Aug 04 '11 at 10:07
9

UPDATE

Changes applied to the DOM elements are not applied immediately, all the changes made to the DOM in a single execution cycle are collected and applied in one repaint.

So you need to wait for the repaint to complete before trying to read the updated dimensions of the element.

requestAnimationFrame is a method that is executed before every repaint.

requestAnimationFrame(() => {
  element = document.getElementById("your_ID");
  let height = element.offsetHeight;
  console.log("debug height: " + height);
});
Dennis
  • 965
  • 1
  • 9
  • 17
HazeyAce
  • 361
  • 3
  • 12
6

Another "trick" is to momentarily set the objects visibility to hidden, its display to block. And then get the offsetHeight. Then just reverse that by setting display to none and visibility to visible. Of course this will only work if it will not disrupt the flow of the page layout (i.e. everything shifts in the page as if something is there, but nothing is displayed in the space). But if it is something that is z-indexed or floating or perhaps absolute positioned it should work fine.

Alexis Pigeon
  • 7,423
  • 11
  • 39
  • 44
0

There is a more easiest way to do that. I had many iframes with different IDs and names so here is what I did. I added the button in the parent window, which on click does this

var iWin = document.querySelector(your iframe id here).contentWindow;
iWin.postMessage("button is clicked","*");
//you can send the id of the required frame as the message

Put this inside the child window script.

window.onload = function(){
          window.addEventListener('message',(e)=>{
            if(e.data == "showcomment"){
              //I am just sending the height and iframe name cause I have many iframes 
              //with different names  
              window.parent.postMessage({winHeight:document.body.offsetHeight,winName: 
              window.name},"*");
            }
          });
    }

Now last step put this in the parent window script

window.addEventListener('message',(e)=>{
//here I am getting element with that name and setting its height you can change it
document.getElementsByName(`${e.data.winName}`)[0].height = e.data.winHeight + 10;
//I added 10 as extra height , you can ignore it

})

Back2Lobby
  • 534
  • 6
  • 12