0

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!!!

Abhishek Pandey
  • 13,302
  • 8
  • 38
  • 68
  • The max-height CSS property seems to work perfectly fine [here](http://jsfiddle.net/pmnc9/3/) when set to e.g. 60%. True, you can't see everything that is in div D because you have div C's overflow set to hidden, and div D is actually taller than its containing div, but that's only because its content is taller, you can't make its content smaller with CSS. Are you looking for `overflow-y: visible`? – Mathijs Flietstra May 09 '13 at 03:29
  • The max-height property works perfectly to set the height of div C. My problem is that when I use it, the height of div D (set with property height: 100%) does not follow. Please see the counter-example I added in my question. Thks – Gabriel Caron L'Écuyer May 09 '13 at 12:00
  • I believe I have found the source of the problem (but not the solution). The div C with max-height set needs to adjust to the size of it's content (div D), but the size of the div D is dependant on the size of it's parent (div C). Therefore, there is a problem. This problem does not occur by using the height property for div C. Any solution is still welcome!!! – Gabriel Caron L'Écuyer May 09 '13 at 13:49

2 Answers2

6

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.

Community
  • 1
  • 1
Mathijs Flietstra
  • 12,900
  • 3
  • 38
  • 67
  • This is a very good explanation of the problem. I was suspecting something like that but you made it very clear. The solution you bring does not work well with max-height, though. I believe the solution is to move my vertical centering of the divs to div D instead of div C, like in this fiddle : [link](http://jsfiddle.net/vJQGS/2/). If you update it to your answer, I will accept it to benefit others. Thanks – Gabriel Caron L'Écuyer May 10 '13 at 00:18
  • Ah, you're right, I should have checked that, I'm setting the `height` and not the `max-height` in my [jsFiddle](http://jsfiddle.net/vGqmC/5/) solution, I will update the answer. – Mathijs Flietstra May 10 '13 at 00:28
0

it's because D is inside of C wouldn't just saying

#D {height: 100%;}

work because that would be telling it to take up 100% of the div it is inside of?

additionally this might help http://css-tricks.com/the-css-box-model/

xkeshav
  • 53,360
  • 44
  • 177
  • 245
Danny Swan
  • 226
  • 2
  • 3
  • 9
  • It works when I use the height property for div C, but not when I use the max-height property for div C... that is my problem. Please see example and counter-example I added to my question. thks. – Gabriel Caron L'Écuyer May 09 '13 at 12:03