Filho com altura máxima: pai transborda 100%

139

Estou tentando entender o que parece ser um comportamento inesperado para mim:

Eu tenho um elemento com uma altura máxima de 100% dentro de um contêiner que também usa uma altura máxima, mas, inesperadamente, o filho excede o pai:

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

Isso é corrigido, no entanto, se o pai receber uma altura explícita:

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

.container {  
    height: 200px;
}

Alguém sabe por que a criança não honraria a altura máxima de seus pais no primeiro exemplo? Por que é necessária uma altura explícita?

iamkeir
fonte

Respostas:

209

Quando você especifica uma porcentagem para max-heightum filho, é uma porcentagem da altura real do pai, e não da mãe max-height, por incrível que pareça . O mesmo se aplica a max-width.

Portanto, quando você não especifica uma altura explícita no pai, não há uma altura base para a qual a criança max-heightseja calculada.max-height calcula para none, permitindo que a criança tenha a maior altura possível. A única outra restrição que atua sobre a criança agora é a max-widthde seu pai e, como a imagem em si é mais alta do que larga, ela excede a altura do contêiner para baixo, a fim de manter sua proporção e ainda ser a maior possível em geral.

Quando você fazer especificar uma altura explícita para o pai, em seguida, a criança sabe que tem que ser, no máximo, 100% do que a altura explícita. Isso permite que ele fique restrito à altura dos pais (mantendo a proporção).

BoltClock
fonte
4
Esta é uma explicação útil, especialmente misturada com a entrada do meu amigo: "altura máxima: 100% (filho) da altura máxima: 100% (pai) = 0 - é por isso que seu filho não está honrando o valor pai".
Iamkeir # 11/13
8
Não tenho certeza de qual resposta aceitar - esta responde ao 'porquê'.
Iamkeir # 11/13
Eu só respondi o 'porquê' porque não tenho certeza qual é seu objetivo, pois não é mencionado explicitamente. Talvez se você elaborar isso, eu posso responder.
BoltClock
Aceitei isso, pois responde à minha pergunta real, obrigado. Observe que a resposta de @ Daniel abaixo oferece uma correção.
iamkeir
No meu caso, display: flex; flex-direction: columnresolvi o problema e adicionei a barra de rolagem que eu queria.
Xdevs23
73

Eu brinquei um pouco. Em uma imagem maior no firefox, obtive um bom resultado ao usar o valor da propriedade herdar. Isso vai ajudá-lo?

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

img {
    max-height: inherit;
    max-width: inherit;
}
Daniel
fonte
Não tenho certeza de qual resposta aceitar - esta responde à 'correção'.
Iamkeir
Aceitou o @BoltClock por responder o porquê, mas obrigado por oferecer uma correção.
Iamkeir # 11/13
1
Além do @BoltClock, minha resposta é exatamente o que ele diz. O CSS está apenas dizendo ao computador como manipular um elemento, mas após os cálculos ele delimitou todos os valores até os valores básicos necessários para renderização, como altura, largura, cor, coordenadas, ... A propriedade herdar está dizendo ao img para pegue o valor "calculado" do pai. Portanto, você obtém os valores calculados para altura e largura nas propriedades css max-height e max-width.
Daniel
2
Isso não funciona quando max:height: 100%em vez de uma altura fixa: jsfiddle.net/umbreak/n6czk9xt/1
Didac Montero
2
Não posso declarar largura e altura como fixas porque meu layout é responsivo dispaly: flex;. Abri um novo thread: Abri um novo thread: stackoverflow.com/questions/29732391/… No entanto, no pior caso, eu poderia usar o Jquery para buscar a largura e a altura reais da img e defini-las na div da imagem pai.
Didac Montero
7

Encontrei uma solução aqui: http://www.sitepoint.com/maintain-image-aspect-ratios-responsive-web-design/

O truque é possível porque existe uma relação entre WIDTH e PADDING-BOTTOM de um elemento. Assim:

pai:

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

filho ( remova todos os css relacionados à largura , ou seja, largura: 100%):

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

Você pode usar a propriedade ajuste de objeto

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

Como sugerido aqui

Uma explicação completa desta propriedade por Chris Mills no Dev.Opera

E ainda melhor em truques CSS

É suportado em

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

Acabei de verificar se o vivaldi e o cromo também são compatíveis (sem surpresa aqui)

Atualmente, não é suportado no IE, mas ... quem se importa ? Além disso, o iOS suporta ajuste de objeto, mas não posição de objeto, mas será em breve.

Luis Sieira
fonte
Boa alternativa! Eu imagino que a flex-box também poderia ajudar, se a degradação graciosa no IE for aceitável.
Iamkeir 06/07
3

Aqui está uma solução para uma pergunta aberta recentemente marcada como uma duplicata dessa pergunta. A <img>tag estava excedendo a altura máxima do pai <div>.

Broken: Fiddle

Trabalho: Violino

Nesse caso, adicionar display:flexas duas <div>tags pai foi a resposta

CrazyPaste
fonte
3

Em vez de usar max-height: 100% / 100%, uma abordagem alternativa de preencher todo o espaço seria usar position: absolute com superior / inferior / esquerda / direita definida como 0.

Em outras palavras, o HTML teria a seguinte aparência:

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

Você pode ver um exemplo ao vivo em Codesandbox - Estouro no CSS Flex / Grid

Tianzhen Lin
fonte
2

Talvez alguém possa explicar as razões por trás do seu problema, mas você pode resolvê-lo especificando a altura do contêiner e depois definindo a altura da imagem como 100%. É importante que widtha imagem apareça antes da 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
fonte
Se eles querem que o contêiner fique menor se a imagem for menor que 200x200, sim, isso deve ser feito com altura mínima / altura máxima.
Cimmanon
2

O mais próximo que posso chegar disso é este exemplo:

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

ou

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

O principal problema é que a altura assume a porcentagem da altura dos contêineres; portanto, procura uma altura definida explicitamente no contêiner pai, não a altura máxima.

A única maneira de contornar isso, até certo ponto, é o violino acima, onde você pode ocultar o excesso, mas o preenchimento ainda atua como espaço visível para a imagem fluir e, portanto, substituir por uma borda sólida funciona (e então adicionando uma caixa de borda para 200px, se essa for a largura que você precisa)

Não tenho certeza se isso se encaixa com o que você precisa, mas o melhor que consigo entender.

ashleynolan
fonte
Infelizmente, cortar a imagem não é o ideal. Obrigado pela sua contribuição embora.
Iamkeir
1

Uma boa solução é não usar a altura no pai e usá-lo apenas no filho com o View Port :

Exemplo de violino: 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
fonte
1

Geralmente, os contêineres geralmente envolvem bem seu conteúdo. Geralmente não funciona tão bem ao contrário: as crianças não preenchem bem seus antepassados. Portanto, defina seus valores de largura / altura no elemento mais interno em vez do mais externo e deixe que os elementos externos envolvam seu conteúdo.

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

img {
    display: block;
    max-height: 200px;
    max-width: 200px;
}
Dave Cousineau
fonte
Boa tomada, eu gosto disso.
iamkeir 10/03
0

Seu contêiner não tem altura.

Adicionar altura: 200px;

para os recipientes css e o gatinho ficará dentro.

Raffael
fonte
Obrigado pela contribuição, mas identifiquei isso no OP.
Iamkeir