views:

1999

answers:

5

I am currently trying to modify a Javascript function that "slides in" a <div>. The script as it is requires you to define the height of the div, so it is mostly useless in dynamically filled <div>s. I found some text on the clientHeight property in javascript, but it would appear that it doesn't support <div>s with display set to none (which is the method used to slide the div in). That makes sense, as the height of that div in the client window is nothing.

Basically I was wondering what other methods you all know of, or if there's a way to get around the clientHeight = 0 when display: none.

Thanks!

Oh, and here's the function I'm using:

function getDivHeight(objName) {
    return boxHeight = document.getElementById(objName).clientHeight;
}
A: 

In IE you could try scrollHeight, but I'm not sure if it will work or if it is cross browser.

jeffamaphone
+1  A: 

I've had luck cloning the element, moving it offscreen, then displaying it to get the client height:

var original = document.getElementById(some_id);
var new_item = original.cloneNode(true);
document.body.appendChild(new_item);  // item already hidden, so it won't show yet.
                                      // you may wish to validate it is hidden first
new_item.style.position = "absolute";
new_item.style.left = "-1000px";
new_item.style.display = "block";
var height = new_item.clientHeight;

EDIT: Looking through the jQuery code, they do exactly what Tsvetomir Tsonev suggests. jQuery temporarily sets the style to "display: block; position: absolute; visibility: none", and then measures the height, swapping the properties back after the measurement.

So, it looks like you're stuck with having to do something hackish, whether it's cloning the node or risking having it flicker in some browsers... I like Tsvetomir's suggestion better than my initial hack as it, at least, doesn't involve cloning a node into the DOM that you don't need. Either way, the element must not be set to "display: none" in order to measure it's height. Isn't the DOM wonderful? :-)

EDIT 2: Also worth noting that, after jQuery gathers the height, it adds allowances for padding, margin and border sizes, so you may need to as well.

Jarret Hardie
That's a good idea, albeit an unfortunate work-around. Thanks for your help.
Bloudermilk
Yup... it spells 'H', 'A', 'C', 'K' :-)
Jarret Hardie
And I'm almost sure Opera will put scrollbars on the document :P
Tsvetomir Tsonev
Is there a clever way to get the padding, margin and border sizes without having to parse every possible method of setting such values? [I.E. border:, border-top-width:, padding (I.E. "5px 5px, "0 4px 3 2px", "5px"), padding-top,]
Bloudermilk
Update: It worked perfectly (In safari "... Odd, since that is how prototype does it, but oh well!
Bloudermilk
No clever way that I'm aware... jquery goes through the explicit variants in the syle "border-top, padding-top, etc".
Jarret Hardie
Glad to hear it. I suspect the 'position: absolute' prevents the document from being re-flowed... but I'm just guessing.
Jarret Hardie
A: 

Yes, an element that is not displayed on the page has no dimensions.

It kind of makes sense. Consider an element that has been created and filled with a bunch of text, but not yet added to the document tree. How high is it? Depends on font-size. How big is font-size? Depends where in the document that div is inserted; its parent font-size would inherit through.

Similarly for an element with “display: none”. It's not rendered, so it has no dimensions. Couldn't we ask “how high would this be if it were ‘display: block’”? Turns out no, because if it were displayed, that in itself could change the dimensions of its parent block, and then the dimension of displayed elements would be inconsistent with the dimensions of non-displayed elements!

The typical solution is to unset “display: none”, measure the height of the element, and then immediately re-set “display: none”. The browser won't redraw in the middle of a bit of JavaScript, so you won't see a flicker on the page.

bobince
+2  A: 

A simple solution is to set it's visibility to "hidden" and it's display to "block" and measure it. However, some modern browsers will manage to update the page layout during this short time and you will get a nasty flicker. The easiest way to overcome this is to place the element in an absolutely positioned container with overflow set to "hidden".

Tsvetomir Tsonev
Well, it works... Sort of. It's coming up short, leaving the last bit of the text cut off. It seems that this might be due to borders, margins or padding, but if we're measuring the hypothetical height, shouldn't those all be accounted for?
Bloudermilk
Odd measurement was due to setting position:absolute... problem solved(ish)
Bloudermilk
Great :) :10char:
Tsvetomir Tsonev
A: 

I nkow you guys solved this a long time ago but I thought I should share this since it quite tricky to get the height of a hidden div tag. heres what I did after reading your post, I placed the div i want to slide inside a 1px height div with overflow set to hidden. you dont even need to set the display of the inner div to none since it is already there and if you use offsetHeight it should return the proper height for all browsers and you can use that height to slide your div up an down.

PEACE!!!