[css] Child with max-height: 100% overflows parent

I'm trying to understand what appears to be unexpected behaviour to me:

I have an element with a max-height of 100% inside a container that also uses a max-height but, unexpectedly, the child overflows the parent:

Test case: http://jsfiddle.net/bq4Wu/16/

.container {  
    background: blue; 
    padding: 10px; 
    max-height: 200px; 
    max-width: 200px; 
}

img { 
    display: block;
    max-height: 100%; 
    max-width: 100%; 
}

This is fixed, however, if the parent is given an explicit height:

Test case: http://jsfiddle.net/bq4Wu/17/

.container {  
    height: 200px;
}

Does anyone know why the child would not honour the max-height of its parent in the first example? Why is an explicit height required?

This question is related to css

The answer is


The closest I can get to this is this example:

http://jsfiddle.net/YRFJQ/1/

or

.container {  
  background: blue; 
  border: 10px solid blue; 
  max-height: 200px; 
  max-width: 200px; 
  overflow:hidden;
  box-sizing:border-box;
}

img { 
  display: block;
  max-height: 100%; 
  max-width: 100%; 
}

The main problem is that the height takes the percentage of the containers height, so it is looking for an explicitly set height in the parent container, not it's max-height.

The only way round this to some extent I can see is the fiddle above where you can hide the overflow, but then the padding still acts as visible space for the image to flow into, and so replacing with a solid border works instead (and then adding border-box to make it 200px if that's the width you need)

Not sure if this would fit with what you need it for, but the best I can seem to get to.


Containers will already generally wrap their content nicely. It often doesn't work as well the other way around: children don't fill their ancestors nicely. So, set your width/height values on the inner-most element rather than the outer-most element, and let the outer elements wrap their contents.

.container {
    background: blue;
    padding: 10px;
}

img {
    display: block;
    max-height: 200px;
    max-width: 200px;
}

Maybe someone else can explain the reasons behind your problem but you can solve it by specifying the height of the container and then setting the height of the image to be 100%. It is important that the width of the image appears before the height.

<html>
    <head>
        <style>
            .container {  
                background: blue; 
                padding: 10px;
                height: 100%;
                max-height: 200px; 
                max-width: 300px; 
            }

            .container img {
                width: 100%;
                height: 100%
            }
        </style>
    </head>
    <body>
        <div class="container">
            <img src="http://placekitten.com/400/500" />
        </div>
    </body>
</html>

You can use the property object-fit

.cover {
    object-fit: cover;
    width: 150px;
    height: 100px;
}

Like suggested here

A full explanation of this property by Chris Mills in Dev.Opera

And an even better one in CSS-Tricks

It's supported in

  • Chrome 31+
  • Safari 7.1+
  • Firefox 36+
  • Opera 26+
  • Android 4.4.4+
  • iOS 8+

I just checked that vivaldi and chromium support it as well (no surprise here)

It's currently not supported on IE, but... who cares ? Also, iOS supports object-fit, but not object-position, but it will soon.


_x000D_
_x000D_
.container {_x000D_
  background: blue;_x000D_
  padding: 10px;_x000D_
  max-height: 200px;_x000D_
  max-width: 200px;_x000D_
  float: left;_x000D_
  margin-right: 20px;_x000D_
}_x000D_
_x000D_
.img1 {_x000D_
  display: block;_x000D_
  max-height: 100%;_x000D_
  max-width: 100%;_x000D_
}_x000D_
_x000D_
.img2 {_x000D_
  display: block;_x000D_
  max-height: inherit;_x000D_
  max-width: inherit;_x000D_
}
_x000D_
<!-- example 1  -->_x000D_
<div class="container">_x000D_
  <img class='img1' src="http://via.placeholder.com/350x450" />_x000D_
</div>_x000D_
_x000D_
<!-- example 2  -->_x000D_
_x000D_
<div class="container">_x000D_
  <img class='img2' src="http://via.placeholder.com/350x450" />_x000D_
</div>
_x000D_
_x000D_
_x000D_

I played around a little. On a larger image in firefox, I got a good result with using the inherit property value. Will this help you?

.container {
    background: blue;
    padding: 10px;
    max-height: 100px;
    max-width: 100px;
    text-align:center;
}

img {
    max-height: inherit;
    max-width: inherit;
}

I found a solution here: http://www.sitepoint.com/maintain-image-aspect-ratios-responsive-web-design/

The trick is possible because it exists a relation between WIDTH and PADDING-BOTTOM of an element. So:

parent:

container {
  height: 0;
  padding-bottom: 66%; /* for a 4:3 container size */
  }

child (remove all css related to width, i.e. width:100%):

img {
  max-height: 100%;
  max-width: 100%;
  position: absolute;     
  display:block;
  margin:0 auto; /* center */
  left:0;        /* center */
  right:0;       /* center */
  }

Here is a solution for a recently opened question marked as a duplicate of this question. The <img> tag was exceeding the max-height of the parent <div>.

Broken: Fiddle

Working: Fiddle

In this case, adding display:flex to the 2 parent <div> tags was the answer


http://jsfiddle.net/mpalpha/71Lhcb5q/

_x000D_
_x000D_
.container {  
display: flex;
  background: blue; 
  padding: 10px; 
  max-height: 200px; 
  max-width: 200px; 
}

img { 
 object-fit: contain;
  max-height: 100%; 
  max-width: 100%; 
}
_x000D_
<div class="container">
  <img src="http://placekitten.com/400/500" />
</div>
_x000D_
_x000D_
_x000D_


Your container does not have a height.

Add height: 200px;

to the containers css and the kitty will stay inside.


Instead of going with max-height: 100%/100%, an alternative approach of filling up all the space would be using position: absolute with top/bottom/left/right set to 0.

In other words, the HTML would look like the following:

<div class="flex-content">
  <div class="scrollable-content-wrapper">
    <div class="scrollable-content">
      1, 2, 3
    </div>
   </div>
</div>
.flex-content {
  flex-grow: 1;
  position: relative;
  width: 100%;
  height: 100%;
}

.scrollable-content-wrapper {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  overflow: auto;
}

.scrollable-content {
}

You can see a live example at Codesandbox - Overflow within CSS Flex/Grid


A good solution is to not use height on the parent and use it just on the child with View Port :

Fiddle Example: https://jsfiddle.net/voan3v13/1/

body, html {
  width: 100%;
  height: 100%;
}
.parent {
  width: 400px;
  background: green;
}

.child {
  max-height: 40vh;
  background: blue;
  overflow-y: scroll;
}