CSS Question

div height set with max-height => make contained div takes full height using css

I have a div C which

height
is set up using
max-height
. This div contains a div D.

I want the contained div D to have the exact same height (and not more) than the containing div C.

If I use the
height
property for div C, like here


  • the height of the div C is set up using
    height: 90%

  • the height of div D is set up using
    height: 100%

  • Then, Everything works fine, and the height of div D equals the
    height of div C



If I use the
max-height
property for div C, like here


  • the height of the div C is set up using
    max-height: 90%

  • the height of div D is set up using
    height: 100%

  • Then, the height of div D is not equals to the height of div C (a lot
    bigger since the content inside it is very long). In the fiddle, it looks good, but if you inspect div D, you will see it's a lot bigger.



But I need to use the
max-height
css property, how can I set up the height of div D to be equals to the one of div C only with css?

<div id="container">
<div id="A">
<div id="B">
<div id="C">
<div id="D">
<div id="D1">D1</div>
<div id="D2">
D2 - very long content
</div>
</div>
</div>
</div>
</div>
</div>


Thanks!!!

Answer Source

The reason why things do not work the way you expect is simply because max-height does not set the height of the containing div. All it does is, as its name implies, set a maximum limit to the height of the div.

Here's a quote from the W3 CSS2 specification on how the percentage heights are calculated on block elements. This might help to shed some light on the matter:

The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly (i.e., it depends on content height), and this element is not absolutely positioned, the value computes to 'auto'.

In your case the height of the containing div is not set explicitly and depends on content height, because when you set the max-height of the containing div to 90%, and there is not enough content to stretch the containing div to 90% of the height of its own containing element, the height of the containing div will be less than 90% of the height of its own containing element.

An attempt to explain what I believe is happening

The browser renders the containing div with an initial height of auto, which computes to 0px as there is no content yet. Along comes the contained div which wants to be rendered with a height of 100% of the height of its containing block, the browser realizes that this is ridiculous, as 100% of 0px is exactly 0px again. So it decides to set the height of the contained div to auto instead. If it didn't do so, then the contained div would never be visible, because no matter what happens next, 100% of the containing block's height of 0px is always going to be 0px. Remember that the browser is trying to stick to this part of the rule quoted above:

The percentage is calculated with respect to the height of the generated box's containing block

ONLY NOW along come some more div's which would like to be rendered inside the contained div. At the moment when the previous decisions were made, the browser didn't yet know about these div's, they're a bit late to the party. If the browser was then to backtrack and fix itself up after it had rendered those div's, it would effectively be breaking the part of the rule quoted above. As it would indirectly* be setting the percentage height of the contained div based on the height of its contents.

Because of this the W3 specification people have come up with the second part of the rule. Which lets the browser decide to set the height of the contained div to auto if the height of its containing div is not set (and therefore defaults to auto).

So you could say that those late div's are lucky that the browser has taken some precautions and is still able to render those div's, as it has been preemptive and has set the height of the contained div to auto to accommodate for latecomers.

*by calculating the height of the containing div based on the height of the contents of the contained div, and then basing the percentage height of the contained div on this value.

In conclusion

Browsers are just sticking to the W3 specification, which is a good thing. Your first fiddle works because the browser makers are adhering to the specification, and your second fiddle doesn't work for the exact same reason.

The solution

You can only fix your issue by making sure that the div which you want to have a height of 90% of the browser window is a direct descendant of a div which has its height set to 100% of the browser window. If the ancestor div is not absolutely placed, every ancestor of the div, all the way up to the html document element, would also have to have a height of 100% set on itself.

The line above is true, except if an ancestor is encountered which is absolutely placed (which would take it out of the regular document flow), without this ancestor itself having an ancestor with position: relative set (which would force its absolute positioning to be based on the position of its relatively positioned parent instead of on the height of the browser window), and this ancestor is set to be the height of the browser window (using top: 0px; bottom: 0px;). In that case the running up the DOM tree will stop at the absolutely positioned ancestor.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download