views:

394

answers:

6

I'm trying to determine the height of a div. This sounds simple, but is complicated by the fact that it's only descendant contents are floated, so asking for the height/outerHeight (using jQuery)/clientHeight/offsetHeight only returns 0, even though it's clear that on the page, it is rendered certainly with a height. Here is an example of the HTML structure:

<div id="root">
   <div class="header"></div>
   <div class="body">
      <div class="text-left" id="text-one">
         <p>Some text taking up multiple lines</p>
      </div>
      <div class="text-right" id="text-two">
         <p>Other text</p>
      </div>
   </div>
</div>

The "text-left" and "text-right" elements have "float: left;" and "float: right;" on them, so when I ask for the height of "root", it tells me it's 0. However, of course, when I get the height of the "text-one" and "text-two", it correctly tells me that it's 20 or whatever.

How can I determine the REAL height of the the "root" element? (For example, if "text-one" had a height of 50 and "text-two" had a height of 20, it would know that the true height is 50)

I imagine there's some kind of logic to work out all the descendant elements' heights and calculate if they're floated etc etc and give me a final figure...but I'm not smart enough to work that out.

Thanks in advance.

EDIT: Please note changing the HTML (to include a "clear", for example) is not an option. I need to be able to tell the height of this div as it is.

+6  A: 

That's because the height is zero. Try viewing this

<html><head><title>test</title></head><body>

<div id="root" style="border:1px solid red">
   <div class="header"></div>
   <div class="body">
      <div class="text-left" id="text-one" style="float: left;">
         <p>Some text taking up multiple lines</p>
      </div>
      <div class="text-right" id="text-two" style="float: right;">
         <p>Other text</p>
      </div>
   </div>
</div></body>

Header is empty, and body only contains elements floated out of the layout, so it also counts as empty, leaving root bereft of content to hold it open.

Also by the same reasoning, the body element is zero height; which you can verify by adding <body style="border:1px solid blue">

Steve Gilham
See section "The Great Collapse" in this article for further explanation: http://css-tricks.com/all-about-floats/
Edd
Of course, technically, it is. But when you view the page, you can clearly see that some of "root"s children have some size. However you want to phrase it, I don't care - the point is I need to find it's size.
+3  A: 

If all #root's children (strictly speaking, descendants) are floated, then it does indeed have a height of zero. Try setting a background colour on it to prove that it occupies no vertical space.

If you get the heights of the two floated elements, then you can take the greater of those:

var height = Math.max(leftHeight, rightHeight);
NickFitz
Take a look at http://jsbin.com/ekego/edit - I have set a background color of green on root, red on text-left and blue on text-right, just to demonstrate.
Russ Cam
I understand that, but I still need to procedurally determine how big it "looks".And yes, I can take the max of the two floats...but what if there's more of them? What if they're nested? Something needs to be smart enough to work all that out.
At this point, you're essentially trying to re-implement the layout engine in script. Are you sure you can't use script to insert a clearing div on page load, even if you don't want to insert it in the HTML?
Steve Gilham
Yeah, I'm starting to come to that conclusion... Good idea about the clearing div though, I'll give that a try. Cheers!
+1  A: 

How about a function that reads all inner divs and stores the maximum height value from the two divs?

I dont think is very correct but here is try:

var max_height = 0;
$.each( $('#root div'), function(x, y){
    var yHeight = $(y).height();
    max_height = ( yHeight > max_height) ? yHeight : max_height;
});
console.log(max_height); //should have the height value.

Working Demo

Elzo Valugi
This is a good start, but it's not going to be clever enough if there's floated DIVs within divs, etc etc...is it?
As in, if you had two divs of height 100px each, that were floated left with clear:both, the total height would be 200px? The answer is no, the current solution will only give you the height of the tallest child div.
Russ Cam
A: 

Set the overflow of the root element to hidden, then its height will stretch to match the inner elements. Tested with the link you posted in another comment, and it works!

#root {
  background-color: lightgreen; /* for demo purposes */
  overflow: hidden;
}

If using a CSS file is not an option, then you can use your jQuery to set the CSS:

$('#root').css( 'overflow', 'hidden' );
// ...then your height code
DisgruntledGoat
As the description says, I can't edit the HTML. I need to determine the size the original HTML, editing isn't an option.
I meant for you to edit the CSS, if that's possible? Just put `#root { overflow: hidden }` in your CSS file.
DisgruntledGoat
OK updated with a clearer answer and JS equivalent.
DisgruntledGoat
A: 

As partly referenced above the problem here is a css issue, specifically clearing of floated elements. An excellent overview of which can be found at www.positioniseverything.net/easyclearing.html. As you are unable to alter the html mark-up you could take the positioniseverthing solution and apply it by adding a class to the parent of the floated elements with js/jQuery,

$('#root .body').addClass('clearfix');

Now you should be able to access the height with,

$('#root').height();

as mentioned above. Hope that helps

paulb
A: 

I deleted an answer because I missed out on what a lot of others has already pointed out: the height is, quite literally, 0, and everything is working. What you need to do to get the height that, in your words, the root div 'seems' to have, is to make that div actually have that height, which can easily be achieved by simply clearing the floats at the end of the div.

<div id="root">
   <div class="header"></div>
   <div class="body">
      <div class="text-left" id="text-one">
         <p>Some text taking up multiple lines</p>
      </div>
      <div class="text-right" id="text-two">
         <p>Other text</p>
      </div>
   </div>
   <div style="clear: both;"></div>
</div>
David Hedlund