Niño con altura máxima: el padre desborda al 100%

139

Estoy tratando de entender lo que parece ser un comportamiento inesperado para mí:

Tengo un elemento con una altura máxima del 100% dentro de un contenedor que también usa una altura máxima pero, inesperadamente, el niño desborda al padre:

Caso de prueba: 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%; 
}

Sin embargo, esto se soluciona si el padre tiene una altura explícita:

Caso de prueba: http://jsfiddle.net/bq4Wu/17/

.container {  
    height: 200px;
}

¿Alguien sabe por qué el niño no honraría la altura máxima de su padre en el primer ejemplo? ¿Por qué se requiere una altura explícita?

iamkeir
fuente

Respuestas:

209

Cuando especifica un porcentaje para max-heightun niño, es un porcentaje de la altura real del padre, no del padre max-height, por extraño que parezca . Lo mismo se aplica a max-width.

Entonces, cuando no especifica una altura explícita en el padre, entonces no hay una altura base para max-heightcalcular el niño, por lo que calcula, lo max-heightque nonepermite que el niño sea lo más alto posible. La única otra restricción que actúa sobre el niño ahora es la max-widthde su padre, y dado que la imagen en sí misma es más alta que ancha, desborda la altura del contenedor hacia abajo, a fin de mantener su relación de aspecto y al mismo tiempo ser lo más grande posible en general.

Cuando haces especificar una altura explícita para el padre, entonces el niño sabe que tiene que ser como máximo el 100% de esa altura explícita. Eso le permite estar limitado a la altura de los padres (mientras mantiene su relación de aspecto).

BoltClock
fuente
44
Esta es una explicación útil, especialmente mezclada con la entrada de mi amigo: "max-height: 100% (child) of max-height: 100% (parent) = 0 - es por eso que su hijo no está honrando su valor padre".
iamkeir
8
No estoy seguro de qué respuesta aceptar: esta responde el "por qué".
iamkeir
Solo respondí el 'por qué' porque no estoy seguro de cuál es su objetivo, ya que no se menciona explícitamente. Tal vez si elaboras eso, puedo responderte.
BoltClock
Acepté esto, ya que responde a mi pregunta real, gracias. Tenga en cuenta que la respuesta de @ Daniel a continuación ofrece una solución.
iamkeir
En mi caso, display: flex; flex-direction: columnresolví el problema y agregué la barra de desplazamiento que quería.
xdevs23
73

Jugué un poco. En una imagen más grande en Firefox, obtuve un buen resultado con el uso del valor de propiedad de herencia. ¿Te ayudará esto?

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

img {
    max-height: inherit;
    max-width: inherit;
}
Daniel
fuente
No estoy seguro de qué respuesta aceptar: esta responde a la 'solución'.
iamkeir
Aceptó @BoltClock por responder el por qué, pero gracias por ofrecer una solución.
iamkeir
1
Además de @BoltClock, mi respuesta es exactamente lo que dice. CSS solo le dice a la computadora cómo manejar un elemento, pero después de los cálculos habrá delimitado todos los valores a los valores básicos necesarios para la representación, como altura, ancho, color, coordenadas, ... La propiedad de herencia le dice al img que tome el valor "calculado" del padre. Entonces obtienes los valores calculados para la altura y el ancho en tus propiedades css max-height y max-width.
Daniel
2
Esto no funciona cuando en max:height: 100%lugar de una altura fija: jsfiddle.net/umbreak/n6czk9xt/1
Didac Montero
2
No puedo declarar el ancho y la altura como fijos porque mi diseño responde dispaly: flex;. Abrí un nuevo hilo: abrí un nuevo hilo: stackoverflow.com/questions/29732391/... Sin embargo, en el peor de los casos, podría usar Jquery para obtener el ancho y la altura reales de img y establecerlos en el div de la imagen principal.
Didac Montero
7

Encontré una solución aquí: http://www.sitepoint.com/maintain-image-aspect-ratios-responsive-web-design/

El truco es posible porque existe una relación entre WIDTH y PADDING-BOTTOM de un elemento. Entonces:

padre:

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

hijo ( eliminar todos los css relacionados con el ancho , es decir, ancho: 100%):

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

Puedes usar la propiedad object-fit

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

Como sugerido aquí

Una explicación completa de esta propiedad por Chris Mills en Dev.Opera

Y aún mejor en CSS-Tricks

Es compatible con

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

Acabo de comprobar que vivaldi y el cromo también lo soportan (no es sorprendente aquí)

Actualmente no es compatible con IE, pero ... ¿a quién le importa ? Además, iOS admite el ajuste de objetos, pero no la posición de los objetos, pero pronto lo hará.

Luis Sieira
fuente
Buena alternativa! Me imagino que la caja flexible también podría ayudar si la degradación elegante en IE es aceptable.
iamkeir
3

Aquí hay una solución para una pregunta abierta recientemente marcada como un duplicado de esta pregunta. La <img>etiqueta excedía la altura máxima del padre<div> .

Roto: violín

Trabajando: violín

En este caso, agregar display:flexa las 2 <div>etiquetas principales fue la respuesta

CrazyPaste
fuente
3

En lugar de ir con la altura máxima: 100% / 100%, se utilizaría un enfoque alternativo para llenar todo el espacio position: absolute con la parte superior / inferior / izquierda / derecha establecida en 0.

En otras palabras, el HTML se vería así:

<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 {
}

Puede ver un ejemplo en vivo en Codesandbox - Desbordamiento dentro de CSS Flex / Grid

Tianzhen Lin
fuente
2

Tal vez alguien más pueda explicar las razones detrás de su problema, pero puede resolverlo especificando la altura del contenedor y luego configurando la altura de la imagen en 100%. Es importante que widthla imagen aparezca antes que 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>
Kevin Brydon
fuente
Si quieren que el contenedor se haga más pequeño si la imagen es más pequeña que 200x200, entonces sí, debe hacerse con altura mínima / altura máxima.
cimmanon
2

Lo más cerca que puedo llegar a esto es este ejemplo:

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

o

.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%; 
}

El problema principal es que la altura toma el porcentaje de la altura de los contenedores, por lo que busca una altura establecida explícitamente en el contenedor principal, no su altura máxima.

La única forma de evitar esto, hasta cierto punto, puedo ver es el violín de arriba donde puede ocultar el desbordamiento, pero luego el relleno sigue actuando como espacio visible para que la imagen fluya, por lo que reemplazarlo con un borde sólido funciona en su lugar (y luego agregando un cuadro de borde para que sea 200px si ese es el ancho que necesita)

No estoy seguro de si esto encajaría con lo que necesita, pero es lo mejor que puedo lograr.

ashleynolan
fuente
Desafortunadamente, recortar la imagen no es ideal. Gracias por tu aporte sin embargo.
iamkeir
1

Una buena solución es no usar la altura en el padre y usarla solo en el niño con View Port :

Ejemplo de violín: 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;
}
tibbus
fuente
1

Por lo general, los contenedores ya envolverán bien su contenido. A menudo no funciona tan bien al revés: los niños no llenan bien a sus antepasados. Por lo tanto, establezca sus valores de ancho / alto en el elemento más interno en lugar del elemento más externo, y deje que los elementos externos envuelvan su contenido.

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

img {
    display: block;
    max-height: 200px;
    max-width: 200px;
}
Dave Cousineau
fuente
Buena toma, me gusta esto.
iamkeir
0

Su contenedor no tiene altura.

Añadir altura: 200 px;

a los contenedores css y el gatito se quedará adentro.

Raffael
fuente
Gracias por el aporte pero identifiqué esto en el OP.
iamkeir