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 .


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;}​

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


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/


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

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.


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

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)


-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);

Obrigado, estava procurando uma solução Css pura.
— Alvaro
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.