Faça div (altura) ocupar a altura restante do pai

107

http://jsfiddle.net/S8g4E/

Eu tenho um contêiner divcom dois filhos. O primeiro filho tem uma determinada altura. Como faço para que o segundo filho ocupe o "espaço livre" do container divsem dar uma altura específica?

No exemplo, o rosa divdeve ocupar também o espaço em branco.


Semelhante a esta pergunta: Como fazer div ocupar a altura restante?

Mas não quero dar posição absoluta .

Alvaro
fonte
Eu tentei também dar a altura do segundo filho 100%, mas não funcionou: jsfiddle.net/S8g4E/1
Alvaro

Respostas:

156

Expandir o #downfilho para preencher o espaço restante #containerpode ser realizado de várias maneiras, dependendo do suporte do navegador que você deseja alcançar e se #uptem ou não uma altura definida.

Amostras

Rede

O gridlayout do CSS oferece outra opção, embora possa não ser tão simples quanto o modelo Flexbox. No entanto, ele requer apenas o estilo do elemento do contêiner:

.container { display: grid; grid-template-rows: 100px }

O grid-template-rowsdefine a primeira linha como uma altura fixa de 100 px e as linhas restantes se esticarão automaticamente para preencher o espaço restante.

Tenho certeza de que o IE11 requer -ms-prefixos, então certifique-se de validar a funcionalidade nos navegadores que você deseja oferecer suporte.

Flexbox

O Módulo de Layout de Caixa Flexívelflexbox do CSS3 ( ) agora é bem suportado e pode ser muito fácil de implementar. Por ser flexível, funciona até quando #upnão tem altura definida.

#container { display: flex; flex-direction: column; }
#down { flex-grow: 1; }

É importante observar que o suporte do IE10 e IE11 para algumas propriedades do flexbox pode ser problemático, e o IE9 ou versões anteriores não têm suporte algum.

Altura Calculada

Outra solução fácil é usar a unidade funcional CSS3calc , como Alvaro aponta em sua resposta , mas exige que a altura do primeiro filho seja um valor conhecido:

#up { height: 100px; }
#down { height: calc( 100% - 100px ); }

É amplamente suportado, com as únicas exceções notáveis ​​sendo <= IE8 ou Safari 5 (sem suporte) e IE9 (suporte parcial). Alguns outros problemas incluem o uso de calc em conjunto com transform ou box-shadow , portanto, certifique-se de testar em vários navegadores se isso for do seu interesse.

Outras Alternativas

Se um suporte mais antigo for necessário, você pode adicionar height:100%;para #downaumentar a altura total do div rosa, com uma ressalva. Isso causará estouro para o contêiner, porque o #upestá empurrando para baixo.

Portanto, você pode adicionar overflow: hidden;ao contêiner para consertar isso.

Alternativamente, se a altura de #upfor fixa, você pode posicioná-lo absolutamente dentro do contêiner e adicionar uma tampa de preenchimento a #down.

E, ainda outra opção seria usar um display de mesa:

#container { width: 300px; height: 300px; border: 1px solid red; display: table;}
#up { background: green; display: table-row; height: 0; }
#down { background: pink; display: table-row;}​
do utilizador
fonte
4
Eu gostaria que #down tivesse #container height - #up height. Portanto, estouro oculto não é o que estou procurando. E também não quero usar a posição absoluta. Obrigado!
Alvaro
@Alvaro, adicionei outra opção, usando exibições de tabela. A desvantagem aqui é a compatibilidade. PS Um elemento posicionado absolutamente dentro de um contêiner com o position: relative;posiciona em relação ao contêiner, não à janela. Então, essa deve ser uma opção viável.
usuário
2
A fileira da tabela deve estar funcionando para você, consulte este jsFiddle para uma prova. O método de posição absoluta, não será capaz de produzir os mesmos resultados que este violino, então podemos riscar isso da lista (# down e #container terão a mesma altura nesse cenário).
usuário
3
Você está pedindo muito, @Alvaro. CSS não é uma linguagem de script; não pode calcular coisas. Você está preso a ilusões ou js.
Jezen Thomas de
1
@Quantastical, obrigado pela ajuda, mas em sua última edição você apenas copiou a resposta que postei. Alguma menção sobre isso, pelo menos, seria bom.
Alvaro
24

Já se passaram quase dois anos desde que fiz essa pergunta. Acabei de sugerir css calc () que resolve este problema que eu tive e pensei que seria bom adicioná-lo caso alguém tenha o mesmo problema. (Aliás acabei usando a posição absoluta).

http://jsfiddle.net/S8g4E/955/

Aqui está o css

#up { height:80px;}
#down {
    height: calc(100% - 80px);//The upper div needs to have a fixed height, 80px in this case.
}

E mais informações sobre isso aqui: http://css-tricks.com/a-couple-of-use-cases-for-calc/

Suporte para navegador: http://caniuse.com/#feat=calc

Alvaro
fonte
1
Eu também tenho usado CSS3 calconde o amplo suporte a navegadores não é tão importante (IE8 e versões anteriores e Safari 5 não suportam).
usuário de
3
Alguma maneira de fazer semelhante com uma #upaltura dinâmica ?
Adam Waite
@AdamWaite, com uma altura #up dinâmica, você vai querer usar a solução de estouro descrita na outra resposta.
usuário
5

Minha resposta usa apenas CSS, e não overflow: hidden ou display: table-row. Exige que o primeiro filho realmente tenha uma determinada altura, mas em sua pergunta você afirma que apenas o segundo filho precisa ter sua altura não especificada, então acredito que você deve achar isso aceitável.

html

<div id="container">
    <div id="up">Text<br />Text<br />Text<br /></div>
    <div id="down">Text<br />Text<br />Text<br /></div>
</div>

css

#container { width: 300px; height: 300px; border:1px solid red;}
#up { background: green; height: 63px; float:left; width: 100% }
#down { background:pink; padding-top: 63px; height: 100%; box-sizing: border-box; }

http://jsfiddle.net/S8g4E/288/

TWR Cole
fonte
2

verifique a demonstração - http://jsfiddle.net/S8g4E/6/

use css -

#container { width: 300px; height: 300px; border:1px solid red; display: table;}
#up { background: green; display: table-row; }
#down { background:pink; display: table-row;}
Dipak
fonte
Você deve adicionar height: 1pxpara #upgarantir que ele tenha o mínimo de altura. Este é o suporte do navegador para display: table: caniuse.com/css-table
thirtydot
Você poderia me mostrar como esta solução pode ser alcançada neste exemplo "mais complexo", por favor: jsfiddle.net/fyNX4 Muito obrigado
Alvaro
2

A menos que eu sou mal-entendido, você pode simplesmente adicionar height: 100%;e overflow:hidden;para #down.

#down { 
    background:pink; 
    height:100%; 
    overflow:hidden;
}​

Demonstração ao vivo

Editar: Uma vez que você não deseja usar overflow:hidden;, você pode usar display: table;para este cenário; no entanto, não é compatível antes do IE 8. ( display: table;suporte )

#container { 
    width: 300px; 
    height: 300px; 
    border:1px solid red;
    display:table;
}

#up { 
    background: green;
    display:table-row;
    height:0; 
}

#down { 
    background:pink;
    display:table-row;
}​

Demonstração ao vivo

Nota: você disse que deseja que a #downaltura seja a #containeraltura menos a #upaltura. A display:table;solução faz exatamente isso e este jsfiddle vai retratá-lo muito claramente.

Josh Mein
fonte
1
Não quero que a #baixa ultrapasse a # altura do recipiente
Alvaro
Acabei de notar isso. Você pode adicionar overflow:hiddena para ocultar o conteúdo extra.
Josh Mein
1
Vou copiar / colar o que disse para MrSlayer: Gostaria que #down tenha #container height - #up height. Portanto, estouro oculto não é o que estou procurando. E também não quero usar a posição absoluta. Obrigado!
Alvaro
O problema com isso é que, se você reverter os dois divs em seu exemplo, o div verde está fora.
Ced
Isso não responde à pergunta de forma alguma. Afirma "Para ocupar toda a altura restante", embora isto ocupe toda a altura restante, haverá estouro.
Giridhar Karnik
1

Você pode usar flutuadores para empurrar o conteúdo para baixo:

http://jsfiddle.net/S8g4E/5/

Você tem um contêiner de tamanho fixo:

#container {
    width: 300px; height: 300px;
}

O conteúdo pode fluir próximo a um flutuador. A menos que definamos o flutuador para largura total:

#up {
    float: left;
    width: 100%;
}

Embora #upe #downcompartilhe a posição superior, #downo conteúdo de só pode começar após a parte inferior do flutuado #up:

#down {
    height:100%;
}​
biziclop
fonte
Observe que, #upna verdade, cobre a parte superior de #down: jsfiddle.net/thirtydot/S8g4E/9
thirtydot
Sim, é assim que funciona. Mas se o OP não precisa de uma borda arredondada ou algo mais sofisticado #up, provavelmente é aceitável.
biziclop
Esta solução está perto, mas eu gostaria que #down tivesse #container height - #up height. (Em sua solução # altura para baixo = # altura do recipiente). Obrigado '
Alvaro
1
@Alvaro: Por que precisa ser assim? Essa solução parece correta na maioria dos casos, mesmo que seja apenas uma ilusão.
trinta dias
Bem, esta pergunta é um exemplo simplificado deste exemplo mais "complexo": jsfiddle.net/fyNX4 Não funcionaria, não?
Alvaro
1

Resumo

Não encontrei uma resposta totalmente satisfatória, então tive que descobrir sozinho.

Meus requisitos:

  • o elemento deve ocupar exatamente o espaço restante quando seu tamanho de conteúdo é menor ou maior que o tamanho do espaço restante (no segundo caso, a barra de rolagem deve ser exibida );
  • a solução deve funcionar quando a altura do pai é calculada , e não especificada ;
  • calc()não deve ser usado porque o elemento restante não deve saber nada sobre os tamanhos de outros elementos;
  • técnicas de layout modernas e familiares , como flexboxes, devem ser usadas.

A solução

  • Transforme em flexboxes todos os pais diretos com altura computada (se houver) e o próximo pai cuja altura seja especificada ;
  • Especifique flex-grow: 1para todos os pais diretos com altura calculada (se houver) e o elemento para que ocupem todo o espaço restante quando o tamanho do conteúdo do elemento for menor;
  • Especifique flex-shrink: 0para todos os itens flexíveis com altura fixa para que não fiquem menores quando o tamanho do conteúdo do elemento for maior que o tamanho do espaço restante;
  • Especifique overflow: hiddenpara todos os pais diretos com altura calculada (se houver) para desativar a rolagem e proibir a exibição de conteúdo de estouro;
  • Especifique overflow: autopara o elemento para permitir a rolagem dentro dele.

JSFiddle (elemento tem pais diretos com altura computada)

JSFiddle (caso simples: sem pais diretos com altura computada)

N. Kudryavtsev
fonte
-3

Não tenho certeza se isso pode ser feito puramente com CSS, a menos que você se sinta confortável em fingir com ilusões. Talvez use a resposta de Josh Mein e defina #containercomo overflow:hidden.

Para valer a pena, aqui está uma solução jQuery:

var contH = $('#container').height(),
upH = $('#up').height();
$('#down').css('height' , contH - upH);
Jezen Thomas
fonte
Obrigado, estava procurando uma solução Css pura.
Alvaro