Como forçar div filho a ser 100% da altura do div pai sem especificar a altura do pai?


535

Eu tenho um site com a seguinte estrutura:

<div id="header"></div>

<div id="main">
  <div id="navigation"></div>
  <div id="content"></div>
</div>

<div id="footer"></div>

A navegação está à esquerda e a divisão de conteúdo está à direita. As informações para a div de conteúdo são extraídas através do PHP, por isso são sempre diferentes.

Como posso dimensionar a navegação verticalmente para que sua altura seja igual à altura da div do conteúdo, independentemente da página carregada?


1
Use a tabela de exibição no pai e a célula da tabela no filho. Isso fará com que o filho contenha o pai. Veja stackoverflow.com/q/22712489/3429430
user31782

3
Você pode apenas definir display: flex; align-items: stretch;o div # main. E não usar height: 100%para div conteúdo #
Igor

Respostas:


167

NOTA : Esta resposta é aplicável a navegadores herdados sem suporte para o padrão Flexbox. Para uma abordagem moderna, consulte: https://stackoverflow.com/a/23300532/1155721


Sugiro que você dê uma olhada nas colunas de altura igual com CSS no navegador cruzado e sem hack .

Basicamente, fazer isso com CSS de maneira compatível com o navegador não é trivial (mas trivial com tabelas); portanto, encontre uma solução pré-empacotada apropriada.

Além disso, a resposta varia se você deseja 100% de altura ou altura igual. Geralmente é igual altura. Se tiver 100% de altura, a resposta é um pouco diferente.


7
Isso parece uma boa solução até você desenhar uma borda, border:1px solid bluepor exemplo container2: on : a borda azul fica nas duas primeiras colunas, não na segunda coluna apenas como você esperaria.
Julien Kronegg

@bfritz, uma solução melhor seria usardisplay:table
Siler

537

Para o pai:

display: flex;

Você deve adicionar alguns prefixos, http://css-tricks.com/using-flexbox/ .

Edit: Como observou @Adam Garner, align-items: stretch; Não é necessário. Seu uso também é para pais, não para filhos. Se você deseja definir o alongamento das crianças, use o self de alinhamento.

.parent {
  background: red;
  padding: 10px;
  display:flex;
}

.other-child {
  width: 100px;
  background: yellow;
  height: 150px;
  padding: .5rem;
}

.child {  
  width: 100px;
  background: blue;
}
<div class="parent">
  <div class="other-child">
    Only used for stretching the parent
  </div>
  <div class="child"></div>
</div>


3
O IE11 não funciona bem com flexbox e alturas. clique em "problemas conhecidos" aqui: caniuse.com/#feat=flexbox
adamdport

@SuperUberDuper Bem, você pode usá-lo no bootstrap como este: jsfiddle.net/prdwaynk Mas se eu fosse você, usaria a fundação que está pronta para produção com o flexbox: foundation.zurb.com/sites/docs/xy-grid.html BS4 também terá Flexbox, mas ainda está em alfa, e acho que a fundação é melhor de qualquer maneira.
Aiphee

4
Se você estiver usando align-items: centero item que você precisa para necessidades estiramentoalign-self: normal
Dominic

2
Esta não é uma resposta certa, porque isso precisa definir a altura dos pais. A pergunta foi feita 'sem especificar a altura dos pais?'.
SkuraZZ 13/03/19

3
@Aiphee votou negativamente porque parece que você não viu a parte de não ter que definir a altura dos pais exatamente no texto da pergunta original, mas sua "solução" faz exatamente isso.
tylerism

99

Esse é um problema frustrante que é tratado com designers o tempo todo. O truque é que você precisa definir a altura para 100% em BODY e HTML em seu CSS.

html,body {
    height:100%;
}

Esse código aparentemente sem sentido é definir para o navegador o que significa 100%. Frustrante, sim, mas é a maneira mais simples.


9
Exceto que nem sempre funciona, por exemplo, se você tem um elemento posicionado relativo dentro de um elemento posicionado absoluto, ele não força mais o hasLayout.
tim

Além disso, se você quiser se livrar da barra de rolagem no lado direito da janela (aparece no Firefox v28), dar a janela algum espaço para respirar: html { height: 100%; } body { height: 98%; }.
Chris Middleton

59
Isso só funciona se todos os pais tiverem 100% de altura, não é suficiente definir apenas o html e o corpo; todos os pais devem ter uma altura definida.
RaduM

97

Acho que definir as duas colunas em display: table-cell;vez de float: left;funciona bem.


10
MS-se não apoiá-lo mais, se isso ajuda ninguém convencer os seus clientes ...
Heraldmonkey

4
Essa deve ser a resposta aceita. Os tempos mudaram, esta resposta funciona em todos os navegadores (com pequenas peculiaridades no Safari 5.1.17). Duas linhas de CSS e você instantaneamente tem o efeito que está procurando, sem nenhum inconveniente que eu possa imaginar.
callmetwan

7
Elevar esta resposta. Coloque as costas nele rapazes!

Esta é a melhor resposta. Sim, podemos criar uma tabela para fazer isso, mas não são dados tabulares. Em vez disso, tratamos os divs como se fossem células da tabela ... Brilhante!
Derokorian

Isso realmente me colocou na direção certa para um cenário diferente. Caso alguém esteja lutando para trabalhar com divs quadrados que também são flex containers no Firefox ou Edge, lembre-se de definir o elemento: before para exibir: table. Não me pergunte o porquê, mas isso corrige.
CGodo 9/07/16

56

Se você não se importa com o div de navegação sendo cortado no caso de um div de conteúdo inesperadamente curto, há pelo menos uma maneira fácil:

#main {
position: relative;
}

#main #navigation {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 10em; /* or whatever */
}

#main #content {
margin: 0;
margin-left: 10em; /* or whatever width you set for #navigation */
}

Caso contrário, há a técnica de colunas falsas .


2
Muito obrigado, você salvou meu dia. Não sabia que se podia definir tanto a parte superior quanto a inferior e funcionaria dessa maneira.
22313

Isso fará com que o conteúdo do contêiner pare de redimensioná-lo.
DreamWave 5/08/13

+1 porque aborda especificamente a pergunta do OP "Como forçar a divisão infantil a 100% da divisão dos pais sem especificar a altura dos pais?" Meu problema não exigia colunas (mencionadas nos detalhes da pergunta, mas não no título principal), mas uma div atrás da outra. Esta resposta funciona em ambos os aplicativos.
Lucas

Esta deve ser a resposta escolhida
Gabriel

32
#main {
    overflow: hidden;
}
#navigation, #content {
    margin-bottom: -1000px;
    padding-bottom: 1000px;
}

Devo dizer que estava procurando esse tipo de solução. Muito simples e tão óbvio que ninguém descobriu. Parabéns @Roman!
precisa saber é o seguinte

15

usando jQuery:

$(function() {
    function unifyHeights() {
        var maxHeight = 0;
        $('#container').children('#navigation, #content').each(function() {
            var height = $(this).outerHeight();
            // alert(height);
            if ( height > maxHeight ) {
                maxHeight = height;
            }
        });
        $('#navigation, #content').css('height', maxHeight);
    }
    unifyHeights();
});

19
Math.max()seria seu amigo aqui.
alex

1
Não foi possível fazer com que o CSS funcionasse em todos os casos para mim; era necessário apenas uma correção rápida. Pode não ser a abordagem mais padrão , mas fez o trabalho muito bem. Obrigado! : -]

1
Ao usar a cssfunção do JQuery , você não pode diferenciar entre tela e mídia de impressão, como costuma fazer ao usar soluções CSS puras. Portanto, você pode ter problemas de impressão.
Julien Kronegg

12

Tente fazer a margem inferior 100%.

margin-bottom: 100%;

6
ou fundo de preenchimento: 100%; não é preciso, mas funciona bem em algumas situações.
Jason

padding-bottom faz o truque no meu caso. Esta solução é muito semelhante à que o @Roman Kuntyi postou.
precisa saber é o seguinte

10
#main {
   display: table;
} 
#navigation, #content {
   display: table-cell;
}

Veja este exemplo .


Isto é exatamente o que eu estava fazendo, queria adicionar uma resposta. Eu também estava usando, height: 100%mas acabou que não era necessário.
jcubic

9

height : <percent>funcionará apenas se você tiver todos os nós principais com uma porcentagem de altura especificada e uma altura fixa em pixels, ems etc. no nível superior. Dessa forma, a altura cairá em cascata até o seu elemento.

Você pode especificar 100% para html e elementos do corpo, como o @Travis afirmou anteriormente, para que a altura da página desça em cascata nos seus nós.


9

Após longa pesquisa e tentativa, nada resolveu meu problema, exceto

style = "height:100%;"

nas crianças div

e para pai aplicar isso

.parent {
    display: flex;
    flex-direction: column;
}

Além disso, estou usando o bootstrap e isso não corrompeu o responsivo para mim.


1
Eu tive que remover flex-direction: column;para que isso funcionasse para mim.
Richard Hedges

6

Com base no método descrito neste artigo , criei a. Menos solução dinâmica:

Html:

<div id="container3">
    <div id="container2">
        <div id="container1">
            <div id="col1">Column 1</div>
            <div id="col2">Column 2</div>
            <div id="col3">Column 3</div>
        </div>
    </div>
</div>

Menos:

/* Changes these variables to adjust your columns */
@col1Width: 60%;
@col2Width: 1%;
@padding: 0%;

/* Misc variable. Do not change */
@col3Width: 100% - @col1Width - @col2Width;

#container3 {
    float: left;
    width: 100%;
    overflow: hidden;
    background-color: red;
    position: relative;

    #container2 {
        float: left;
        width: 100%;
        position: relative;
        background-color: yellow;
        right: @col3Width;

        #container1 {
            float: left;
            width: 100%;
            position: relative;
            right: @col2Width;
            background-color: green;

            #col1 {
                float: left;
                width: @col1Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding;
                overflow: hidden;
            }

            .col2 {
                float: left;
                width: @col2Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 2;
                overflow: hidden;
            }

            #col3 {
                float: left;
                width: @col3Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 4;
                overflow: hidden;
            }
        }
    }
}


3

Eu sei que já faz muito tempo desde que a pergunta foi feita, mas achei uma solução fácil e achei que alguém poderia usá-la (desculpe pelo inglês ruim). Aqui vai:

CSS

.main, .sidebar {
    float: none;
    padding: 20px;
    vertical-align: top;
}
.container {
    display: table;
}
.main {
    width: 400px;
    background-color: LightSlateGrey;
    display: table-cell;
}
.sidebar {
    width: 200px;
    display: table-cell;
    background-color: Tomato;
}

HTML

<div class="container clearfix">
    <div class="sidebar">
        simple text here
    </div>
    <div class="main">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue, tortor in mattis mattis, arcu erat pharetra orci, at vestibulum lorem ante a felis. Integer sit amet est ac elit vulputate lobortis. Vestibulum in ipsum nulla. Aenean erat elit, lacinia sit amet adipiscing quis, aliquet at erat. Vivamus massa sem, cursus vel semper non, dictum vitae mi. Donec sed bibendum ante.
    </div>
</div>

Exemplo simples. Observe que você pode se transformar em capacidade de resposta.


Ah, esqueci: se você deseja alinhar o conteúdo da barra lateral no meio, basta alterar "vertical-align: top" para "vertical-align: top".
Paula Fleck

2

Minha solução:

$(window).resize(function() {
   $('#div_to_occupy_the_rest').height(
        $(window).height() - $('#div_to_occupy_the_rest').offset().top
    );
});

1

Existe um pouco de contradição no título e no conteúdo da pergunta. O título fala de uma div pai, mas a pergunta faz parecer que você deseja que duas divs irmãos (navegação e conteúdo) tenham a mesma altura.

Você (a) deseja que a navegação e o conteúdo tenham 100% da altura do principal ou (b) deseja que a navegação e o conteúdo tenham a mesma altura?

Eu assumo (b) ... se é assim, acho que você não será capaz de fazê-lo, dada sua estrutura de página atual (pelo menos, não com CSS puro e sem scripts). Você provavelmente precisaria fazer algo como:

<main div>
    <content div>
         <navigation div></div>
    </div>
</div>

e defina a div de conteúdo para ter uma margem esquerda, independentemente da largura do painel de navegação. Dessa forma, o conteúdo do conteúdo fica à direita da navegação e você pode definir a div de navegação como 100% da altura do conteúdo.

EDIT: Estou fazendo isso completamente na minha cabeça, mas você provavelmente também precisará definir a margem esquerda da div de navegação para um valor negativo ou definir sua esquerda absoluta para 0 para empurrá-la de volta para a extrema esquerda. O problema é que existem muitas maneiras de fazer isso, mas nem todas serão compatíveis com todos os navegadores.


1

[Referindo-se ao código Menos de Dmity em outra resposta] Estou supondo que isso seja algum tipo de "pseudo-código"?

Pelo que entendi, tente usar a técnica de colunas falsas que deve resolver o problema.

http://www.alistapart.com/articles/fauxcolumns/

Espero que isto ajude :)


4
Dependendo da ordem de classificação das respostas, é difícil dizer a que "isso" se refere ... Acho que se trata do código de Dmitry. Assim, esta observação pertence a um comentário abaixo de sua resposta! E, para sua informação, não é pseudo-código, é código na linguagem Menos, uma maneira de definir CSS de maneira processual.
PhiLho 29/04

1

Este truque funciona: Adicionando um elemento final em sua seção de HTML com um estilo de clear: both;

    <div style="clear:both;"></div>

Tudo antes disso será incluído na altura.


1

dando position: absolute;para a criança trabalhou no meu caso


1

Você usa CSS Flexbox

.flex-container {
  display: flex;
  background-color: DodgerBlue;
}

.flex-container > div {
  background-color: #f1f1f1;
  margin: 10px;
  padding: 20px;
  font-size: 30px;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>

<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div>3</div>  
</div>

<p>A Flexible Layout must have a parent element with the <em>display</em> property set to <em>flex</em>.</p>

<p>Direct child elements(s) of the flexible container automatically becomes flexible items.</p>

</body>
</html>


1

Essa resposta não é mais ideal, já que a CSS flexbox e grade foram implementadas no CSS. No entanto, ainda é uma solução funcional

Em uma tela menor, você provavelmente desejaria manter a altura automática, pois as colunas col1, col2 e col3 são empilhadas uma sobre a outra.

No entanto, após um ponto de interrupção da consulta à mídia, você deseja que as colunas apareçam próximas uma da outra com uma altura igual para todas as colunas.

1125 px é apenas um exemplo de ponto de interrupção da largura da janela, após o qual você deseja definir todas as colunas com a mesma altura.

<div class="wraper">
    <div class="col1">Lorem ipsum dolor sit amet.</div>
    <div class="col2">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eos laudantium, possimus sed, debitis amet in, explicabo dolor similique eligendi officia numquam eaque quae illo magnam distinctio odio, esse vero aspernatur.</div>
    <div class="col3">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorem, odio qui praesentium.</div>
</div>

Obviamente, você poderia definir mais pontos de interrupção, se necessário.

<script>
    $(document).ready(function(){
        $(window).on('load resize', function() {
            let vraperH = $('.wraper').height();
            if (window.innerWidth>= 1125) {
              $('.col1').height(vraperH);
              $('.col2').height(vraperH);
              $('.col3').height(vraperH);
            }
            if (window.innerWidth < 1125) {
              $('.col1').height('auto');
              $('.col2').height('auto');
              $('.col3').height('auto');
            }
        });
    });
</script>

1

Eu tive o mesmo problema, funcionou com base na resposta de Hakam Fostok, criei um pequeno exemplo; em alguns casos, ele pode funcionar sem precisar adicionar display: flex;e flex-direction: column;no contêiner pai

.row {
    margin-top: 20px;
}

.col {
    box-sizing: border-box;
    border: solid 1px #6c757d;
    padding: 10px;
}

.card {
    background-color: #a0a0a0;
    height: 100%;
}

JSFiddle


0

Como mostrado anteriormente, o flexbox é o mais fácil. por exemplo.

#main{ display: flex; align-items:center;}

isso alinhará todos os elementos filhos ao centro dentro do elemento pai.


3
isso não responder à pergunta, eles querem a mesma altura, não centrar o conteúdo
Ryan M


0

Aqui, uma demonstração de moda antiga baseada no position: absolutecontêiner de conteúdo e position: relativeno contêiner pai.

Quanto à maneira moderna de fazer isso - as caixas flex são as melhores.


-3

A maneira mais fácil de fazer isso é fingir. A List Apart cobriu isso extensivamente ao longo dos anos, como neste artigo de Dan Cederholm de 2004 .

Aqui está como eu costumo fazer isso:

<div id="container" class="clearfix" style="margin:0 auto;width:950px;background:white url(SOME_REPEATING_PATTERN.png) scroll repeat-y center top;">
    <div id="navigation" style="float:left;width:190px;padding-right:10px;">
        <!-- Navigation -->
    </div>
    <div id="content" style="float:left;width:750px;">
        <!-- Content -->
    </div>
</div>

É possível adicionar facilmente um cabeçalho a esse design, envolvendo #container em outra div, incorporando a div do cabeçalho como # irmão do contêiner e movendo os estilos de margem e largura para o contêiner pai. Além disso, o CSS deve ser movido para um arquivo separado e não mantido em linha etc. etc. Finalmente, a classe clearfix pode ser encontrada em positioniseverthing .

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.