1

Here is the snippet (demo available on JsFiddle)

#outer {
    display: table;
    height: 200px;
    width: 100%;
    background: gray;
}

#inner {
    width: 100%;
    background: blue;
    max-height: 100%;
}
<div id="outer">
    <img id="inner" src="http://jsfiddle.net/img/logo.png">
</div>

The parent element uses display:table (which is set by a third-party framework), and I set max-height:100% in the child element for constrain.

However, as can be seen in the demo above (I'm using Chrome 46.0), the child element's height becomes "ZERO" somehow..

When I removed display:table attributes in the parent element, everything works fine again.

I checked the MDN document for max-height. When mentioning the percentage value of max-height, it says:

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 percentage value is treated as none.

As I understand for my demo, the #inner element's containing block is specified explicity to #outer, so the max-height: 100% attribute in #inner will be equivalent to height: 200px. Is it true? Does anyone have ideas about where I went wrong?

Thanks!

Hanfei Sun
  • 45,281
  • 39
  • 129
  • 237

1 Answers1

6

When you have a parent element and a child element, and the parent element is display: table, the child element is implicitly display: table-cell. (Technically the child element is wrapped in an anonymous table-cell box and the actual child element itself doesn't change, but in this specific scenario it doesn't make a difference.)

So you're attempting to set max-height on a table cell, and at that point you're venturing into undefined behavior:

In CSS 2.1, the effect of 'min-height' and 'max-height' on tables, inline tables, table cells, table rows, and row groups is undefined.

For what it's worth, only Chrome exhibits this problem; the image displays as expected in Firefox and IE. Still, it's hard to say which browser is right or wrong.

As I understand for my demo, the #inner element's containing block is specified explicity to #outer, so the max-height: 100% attribute in #inner will be equivalent to height: 200px. Is it true? Does anyone have ideas about where I went wrong?

No, the containing block of a table cell is not the table itself but the containing block of the table, because a table is a table, not a block container box. See section 10.1:

  1. For other elements, if the element's position is 'relative' or 'static', the containing block is formed by the content edge of the nearest block container ancestor box.

Based on what MDN and the spec say about max-height (the words are almost exactly the same), the used max-height should be none. For whatever reason, Chrome is clamping it to zero instead. Whether it's doing this deliberately to drive home the point about undefined behavior (as Firefox so loves doing with absposed table-cell elements), or if it's due to an unintentional browser quirk, is up for debate, but I'd advise you to find some other workaround for the display: table restriction that's being imposed by your third-party framework.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Thanks, but one thing I can't understand clearly: the computed value of `display` of `#inner` is `inline` instead of `table-cell` when I check it in the browser.. As I set the `max-height` attribute of the `#inner` element instead of its wrapper (the anonymous table-cell box), I don't think that will lead to undefined behaviour. Is it true? – Hanfei Sun Oct 24 '15 at 07:36