Expanda uma div para preencher a largura restante

552

Eu quero um layout div de duas colunas, onde cada um pode ter largura variável, por exemplo

div {
  float: left;
}

.second {
  background: #ccc;
}
<div>Tree</div>
<div class="second">View</div>

Eu quero que a div 'view' se expanda para toda a largura disponível após a div 'tree' preencher o espaço necessário.

Atualmente, minha div 'view' é redimensionada para o conteúdo que ela contém. Também será bom se ambas as divs ocuparem toda a altura.


Isenção de responsabilidade não duplicada:

Anurag Uniyal
fonte
1
relacionada stackoverflow.com/a/22719552/759452
Adrien Seja
1
Ou eu não entendo a pergunta ou eu não entendo como você escolher a resposta aceita, porque há duas larguras e alturas são fixados com o inconveniente deoverflow hidden
user10089632

Respostas:

1012

A solução para isso é realmente muito fácil, mas nem um pouco óbvia. Você precisa acionar algo chamado "contexto de formatação de bloco" (BFC), que interage com os flutuadores de uma maneira específica.

Apenas pegue a segunda div, remova a bóia e dê-a overflow:hiddenem seu lugar. Qualquer valor de estouro diferente de visível faz com que o bloco em que está definido se torne um BFC. Os BFCs não permitem que carros alegóricos descendentes os escapem, nem permitem que carros alegóricos / ancestrais os invadam. O efeito líquido aqui é que a div flutuada fará o que quiser, então a segunda div será um bloco comum, ocupando toda a largura disponível, exceto a ocupada pela flutuação .

Isso deve funcionar em todos os navegadores atuais, embora você precise acionar o hasLayout no IE6 e 7. Não consigo me lembrar.

Demonstrações:

Xanthir
fonte
28
Excelente resposta! Mas você está errado quando diz que "qualquer valor de excesso que não seja automático" o tornará um BFC. O que você quer dizer é que qualquer valor de estouro diferente do padrão (visível) o tornará um BFC. De fato, o overflow auto também funciona perfeitamente - é o que eu recomendaria (apenas no caso de você ter elementos relativamente posicionados que possam aparecer nessa div).
BT
52
Este artigo tem uma boa explicação: colinaarts.com/articles/the-magic-of-overflow-hidden
Max Cantor
1
E se o conteúdo for grande o suficiente para estourar a div?
Giannis christofakis
11
É importante notar que a ordem das crianças é importante. O elemento flutuante com largura fixa deve estar acima do outro. Demorei muito para descobrir, por que não funcionou para mim com ordem trocada.
Riplexus 12/10
2
Eu escrevi uma resposta explicando por que um estouro não visível de todas as coisas aciona um BFC, com base nas respostas de David e Boris, que podem ser encontradas aqui: stackoverflow.com/questions/9943503/… Minha interpretação estava correta?
BoltClock
105

Acabei de descobrir a mágica das caixas flexíveis (display: flex). Tente o seguinte:

<style>
  #box {
    display: flex;
  }
  #b {
    flex-grow: 100;
    border: 1px solid green;
  }
</style>
<div id='box'>
 <div id='a'>Tree</div>
 <div id='b'>View</div>
</div>

As caixas flexíveis me dão o controle que eu gostaria que o css tivesse há 15 anos. Está finalmente aqui! Mais informações: https://css-tricks.com/snippets/css/a-guide-to-flexbox/

BT
fonte
Não sei o que você descobriu, mas seu código não está funcionando no Chrome mais recente jsfiddle.net/fjb548kw/3
Yevgeniy Afanasyev
@YevgeniyAfanasyev removi o "float: left;" para corrigir o problema. Obrigado pela observação!
BT
Obrigado. Você pode explicar por que você tem em flex-grow: 100;vez de flex-grow: 1;?
Yevgeniy Afanasyev
2
@YevgeniyAfanasyev Nenhuma razão em particular, exceto que é assim que eu gosto de fazê-lo. Isso me permite pensar em porcentagens, então, se eu pudesse fazer algo como definir #a como flex-grow:10e então eu definiria # como flex-grow: 90# seria 10% da largura da linha e #b seria 90% da largura da linha. Se nenhum outro elemento tiver um estilo de largura flexível, não importa tecnicamente o que você coloca.
BT
isso funcionou melhor para mim, tentando colocar uma entrada e um botão lado a lado como se fossem um.
Souleste 07/02
29

Solução Flexbox

É para isso que serve a flex-growpropriedade.

html, body {
  height: 100%;
}
body {
  display: flex;
}
.second {
  flex-grow: 1;
}
<div style="background: #bef;">Tree</div>
<div class="second" style="background: #ff9;">View</div>

Nota: Adicione prefixos de fornecedor flex, se necessário pelos navegadores suportados .

Reggie Pinkham
fonte
27

Este seria um bom exemplo de algo que é trivial para fazer com tabelas e difícil (se não impossível, pelo menos no sentido entre navegadores) com CSS.

Se as duas colunas tivessem largura fixa, isso seria fácil.

Se uma das colunas tivesse largura fixa, isso seria um pouco mais difícil, mas totalmente factível.

Com as duas colunas de largura variável, IMHO, você precisa apenas usar uma tabela de duas colunas.

cleto
fonte
11
A tabela não será muito boa em um design responsivo, no qual você deseja que a coluna da direita deslize para a esquerda em pequenos dispositivos.
S ..
1
Existem alguns truques design responsivo para trabalhar com tabelas: css-tricks.com/responsive-data-tables
Rikki
Atualmente, costumo projetar dois layouts separados completamente e mudar em um celular usando consultas de mídia. display:none;Ao mesmo tempo em que, o máximo possível, é 100% responsivo em uma escala móvel, às vezes é melhor mudar completamente o design para um celular usando a sensação da tela de toque e estilo do botão.
Bysander
22

Confira esta solução

.container {
  width: 100%;
  height: 200px;
  background-color: green;
}
.sidebar {
  float: left;
  width: 200px;
  height: 200px;
  background-color: yellow;
}
.content {
  background-color: red;
  height: 200px;
  width: auto;
  margin-left: 200px;
}
.item {
  width: 25%;
  background-color: blue;
  float: left;
  color: white;
}
.clearfix {
  clear: both;
}
<div class="container">
  <div class="clearfix"></div>
  <div class="sidebar">width: 200px</div>

  <div class="content">
    <div class="item">25%</div>
    <div class="item">25%</div>
    <div class="item">25%</div>
    <div class="item">25%</div>
  </div>
</div>

angel.dimitrov
fonte
2
Geralmente, essa é uma solução superior porque nem sempre é possível ocultar o estouro.
Joseph Lennox
3
Por OP: "Quero um layout div de duas colunas, em que cada uma possa ter largura variável". Na sua resposta, você precisa saber a largura da primeira coluna, para que não seja variável. Você também pode definir larguras fixas nas duas colunas e apenas flutuá-las.
23415 Jacob Javarez
17

Use calc:

.leftSide {
  float: left;
  width: 50px;
  background-color: green;
}
.rightSide {
  float: left;
  width: calc(100% - 50px);
  background-color: red;
}
<div style="width:200px">
  <div class="leftSide">a</div>
  <div class="rightSide">b</div>
</div>

O problema disso é que todas as larguras devem ser explicitamente definidas, como um valor (px e em funcionam bem) ou como uma porcentagem de algo explicitamente definido.

joel Moses
fonte
15

Aqui, isso pode ajudar ...

<html>

<head>
  <style type="text/css">
    div.box {
      background: #EEE;
      height: 100px;
      width: 500px;
    }
    div.left {
      background: #999;
      float: left;
      height: 100%;
      width: auto;
    }
    div.right {
      background: #666;
      height: 100%;
    }
    div.clear {
      clear: both;
      height: 1px;
      overflow: hidden;
      font-size: 0pt;
      margin-top: -1px;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="left">Tree</div>
    <div class="right">View</div>
    <div class="clear" />
  </div>
</body>

</html>

a6hi5h3k
fonte
+1 porque o seu exemplo parece funcionar, mas, no meu cenário real, de alguma forma, como o conteúdo de 'view' se arrasta para a 'tree' div, como tree div não é 100%, pode haver algum javascript obriga a ser pequeno e após a altura da árvore vejo conteúdos vista
Anurag Uniyal
Nesse caso, se você souber a largura máxima da coluna esquerda, poderá atribuir a ela um estilo de largura máxima (não funciona no IE) ou pensar em margem esquerda (cuidado com o erro de margem dupla no IE) ou padding-left.
A6hi5h3k
Isso foi ótimo! Eu estou usando-o em linha como uma solução one-off:<div class="clear" style="clear: both; height: 1px; overflow: hidden; font-size:0pt; margin-top: -1px;"></div>
ajwest
5

Não entendo por que as pessoas estão dispostas a trabalhar tanto para encontrar uma solução de CSS puro para layouts colunares simples que são TÃO FÁCIL usando a TABLEtag antiga .

Todos os navegadores ainda têm a lógica do layout da tabela ... Talvez me chame de dinossauro, mas eu digo: deixe-o ajudá-lo.

<table WIDTH=100% border=0 cellspacing=0 cellpadding=2>
  <tr>
    <td WIDTH="1" NOWRAP bgcolor="#E0E0E0">Tree</td>
    <td bgcolor="#F0F0F0">View</td>
  </tr>
</table>

Muito menos arriscado em termos de compatibilidade entre navegadores também.

PatM
fonte
2
sim, mas se tudo está sendo feito pelo css, por que não isso, pelo menos uma curiosidade, se possível?
Anurag Uniyal
2
Isso porque se você deseja media-queriescolocar as duas colunas uma acima da outra em pequenos dispositivos, é impossível com a tabletag antiga . Para que isso funcione, você precisa aplicar CSSestilos de tabela. Portanto, hoje em dia é melhor resolver isso CSSse você quiser um layout responsivo para qualquer tamanho de tela.
ElChiniNet
5

Se a largura da outra coluna for fixa, que tal usar a calcfunção CSS para todos os navegadores comuns :

width: calc(100% - 20px) /* 20px being the first column's width */

Dessa forma, a largura da segunda linha será calculada (ou seja, a largura restante) e aplicada de forma responsiva.

anit
fonte
Esta é a melhor resposta na medida em que você usa qualquer outra coisa que não seja o flexbox, como por exemplo css-grid. Também funciona com o position: fixedque torna tudo em torno de escolha perfeita! Obrigado!
Bartekus 10/01
3

<html>

<head>
  <style type="text/css">
    div.box {
      background: #EEE;
      height: 100px;
      width: 500px;
    }
    div.left {
      background: #999;
      float: left;
      height: 100%;
      width: auto;
    }
    div.right {
      background: #666;
      height: 100%;
    }
    div.clear {
      clear: both;
      height: 1px;
      overflow: hidden;
      font-size: 0pt;
      margin-top: -1px;
    }
  </style>
</head>

<body>
  <div class="box">
    <div class="left">Tree</div>
    <div class="right">View</div>
    <div class="right">View</div>
    <div style="width: <=100% getTreeWidth()100 %>">Tree</div>
    <div class="clear" />
  </div>
  <div class="ColumnWrapper">
    <div class="Colum­nOne­Half">Tree</div>
    <div class="Colum­nOne­Half">View</div>
  </div>

</body>

</html>

A.Pramod Kumar
fonte
Quero algo como uma barra de status com itens fixos à esquerda, itens fixos à direita e uma linha de mensagem que use toda a esquerda no espaço. Comecei com esta resposta e adicionei minha mensagem div APÓS os carros alegóricos com: height: 20px; espaço em branco: nowrap; estouro: oculto; text-overflow: clip
englebart
3

Você pode tentar o CSS Grid Layout .

dl {
  display: grid;
  grid-template-columns: max-content auto;
}

dt {
  grid-column: 1;
}

dd {
  grid-column: 2;
  margin: 0;
  background-color: #ccc;
}
<dl>
  <dt>lorem ipsum</dt>
  <dd>dolor sit amet</dd>
  <dt>carpe</dt>
  <dd>diem</dd>
</dl>

cânone
fonte
2

flex-grow - define a capacidade de um item flex crescer, se necessário. Ele aceita um valor sem unidade que serve como proporção. Ele determina qual quantidade de espaço disponível dentro do contêiner flexível o item deve ocupar.

Se todos os itens tiverem o crescimento flexível definido como 1, o espaço restante no contêiner será distribuído igualmente a todos os filhos. Se um dos filhos tiver um valor 2, o espaço restante ocupará o dobro do espaço que os outros (ou tentará, pelo menos). Veja mais aqui

.parent {
  display: flex;
}

.child {
  flex-grow: 1; // It accepts a unitless value that serves as a proportion
}

.left {
  background: red;
}

.right {
  background: green;
}
<div class="parent"> 
  <div class="child left">
      Left 50%
  </div>
   <div class="child right">
      Right 50%
  </div>
</div>

Stanislav Ostapenko
fonte
1

Uma implementação ligeiramente diferente,

Dois painéis div (conteúdo + extra), lado a lado, content panelse expandem se extra panelnão estiver presente.

jsfiddle: http://jsfiddle.net/qLTMf/1722/

Rao
fonte
1

Pat - Você está certo. É por isso que essa solução satisfaria tanto os "dinossauros" quanto os contemporâneos. :)

.btnCont {
  display: table-layout;
  width: 500px;
}

.txtCont {
  display: table-cell;
  width: 70%;
  max-width: 80%;
  min-width: 20%;
}

.subCont {
  display: table-cell;
  width: 30%;
  max-width: 80%;
  min-width: 20%;
}
<div class="btnCont">
  <div class="txtCont">
    Long text that will auto adjust as it grows. The best part is that the width of the container would not go beyond 500px!
  </div>
  <div class="subCont">
    This column as well as the entire container works like a table. Isn't Amazing!!!
  </div>
</div>

johnmanoahs
fonte
2
Não há nenhuma referência html para o .IP classe css e ele não funciona no IE7
Keith K
1

Você pode usar a biblioteca CSS do W3 que contém uma classe chamada restque faz exatamente isso:

<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

<div class="w3-row">
  <div class="w3-col " style="width:150px">
    <p>150px</p>
  </div>
  <div class="w3-rest w3-green">
    <p>w3-rest</p>
  </div>
</div>

Não se esqueça de vincular a biblioteca CSS nas páginas da página header:

<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

Aqui está a demonstração oficial: W3 School Tryit Editor

manar
fonte
Parece que apenas adiciona "overflow: hidden", o que a torna uma versão pior da resposta já dada
vpzomtrrfrt
0

Não tenho certeza se essa é a resposta que você espera, mas por que você não define a largura da Árvore como 'automática' e a largura da 'Visualização' como 100%?


fonte
3
Porque isso colocará o segundo flutuador abaixo do primeiro porque é muito largo.
Cletus
0

Dê uma olhada nas estruturas de layout CSS disponíveis. Eu recomendaria Simpl ou, a estrutura Blueprint, um pouco mais complexa.

Se você estiver usando o Simpl (que envolve a importação de apenas um arquivo simpl.css ), você pode fazer o seguinte:

<div class="Colum­nOne­Half">Tree</div>
<div class="Colum­nOne­Half">View</div>

, para um layout 50-50, ou:

<div class="Colum­nOne­Quarter">Tree</div>
<div class="Colum­nThreeQuarters">View</div>

, para um 25-75.

É simples assim.


fonte
as duas colunas terão largura variável?
Anurag Uniyal 12/08/09
0

Obrigado pelo plug do Simpl.css!

lembre-se de agrupar todas as suas colunas da ColumnWrappermesma forma.

<div class="ColumnWrapper">
    <div class="Colum­nOne­Half">Tree</div>
    <div class="Colum­nOne­Half">View</div>
</div>

Estou prestes a lançar a versão 1.0 do Simpl.css, então ajude a espalhar a palavra!

Shaggy
fonte
0

Eu escrevi uma função javascript que chamo de jQuery $ (document) .ready (). Isso analisará todos os filhos da div pai e atualizará apenas o filho mais correto.

html

...
<div class="stretch">
<div style="padding-left: 5px; padding-right: 5px; display: inline-block;">Some text
</div>
<div class="underline" style="display: inline-block;">Some other text
</div>
</div>
....

javascript

$(document).ready(function(){
    stretchDivs();
});

function stretchDivs() {
    // loop thru each <div> that has class='stretch'
    $("div.stretch").each(function(){
        // get the inner width of this <div> that has class='stretch'
        var totalW = parseInt($(this).css("width"));
        // loop thru each child node
        $(this).children().each(function(){
            // subtract the margins, borders and padding
            totalW -= (parseInt($(this).css("margin-left")) 
                     + parseInt($(this).css("border-left-width")) 
                     + parseInt($(this).css("padding-left"))
                     + parseInt($(this).css("margin-right")) 
                     + parseInt($(this).css("border-right-width")) 
                     + parseInt($(this).css("padding-right")));
            // if this is the last child, we can set its width
            if ($(this).is(":last-child")) {
                $(this).css("width","" + (totalW - 1 /* fudge factor */) + "px");
            } else {
                // this is not the last child, so subtract its width too
                totalW -= parseInt($(this).css("width"));
            }
        });
    });
}
bcr666
fonte
0

Isso é bastante fácil usando o flexbox. Veja o trecho abaixo. Adicionei um contêiner de invólucro para controlar o fluxo e definir uma altura global. Também foram adicionadas bordas para identificar os elementos. Observe que os divs agora também se expandem para a altura total, conforme necessário. Os prefixos do fornecedor devem ser usados ​​para o flexbox em um cenário do mundo real, pois ainda não é totalmente suportado.

Desenvolvi uma ferramenta gratuita para entender e projetar layouts usando o flexbox. Confira aqui: http://algid.com/Flex-Designer

.container{
    height:180px;
    border:3px solid #00f;
    display:flex;
    align-items:stretch;
}
div {
    display:flex;
    border:3px solid #0f0;
}
.second {
    display:flex;
    flex-grow:1;
    border:3px solid #f00;
}
<div class="container">
    <div>Tree</div>
    <div class="second">View</div>
</div>

Mario Vázquez
fonte
você leu TODAS as respostas anteriores antes de adicionar a sua? que não parece ...
temanitas Afif
Como uma nota lateral, você não precisa adicionar stretchporque é o valor padrão e não há necessidade de fazer o recipiente flexível elemento filho assim display:flexé inútil para os elementos internos
temanitas Afif
Eu me pergunto por que o voto negativo, sem nenhum comentário. Esta resposta não está respondendo à pergunta? Por quê? Se tentar ajudar os outros é penalizado I vai pensar duas vezes antes da minha próxima resposta,
Mario Vázquez
1
você recebeu dois comentários após o voto negativo, não é suficiente?
Temani Afif
Temari, você viu minha ferramenta? Você não acha que é útil e pode ajudar os outros? Você acha que não está relacionado à pergunta? Onde está sua resposta para essa pergunta? Eu não consigo ver. Qual é o seu papel aqui?
Mario Vázquez
-3

Se as duas larguras são de tamanho variável, por que você não calcula a largura com algum script ou lado do servidor?

<div style="width: <=% getTreeWidth() %>">Tree</div>

<div style="width: <=% getViewWidth() %>">View</div>
amischiefr
fonte
3
Como o servidor sabe como o mecanismo de layout do cliente funcionará?
Kev
Simples: desenvolva-o para 90% dos navegadores disponíveis :) IE 7+, FF3 + e Safari suportam CSS 3. Você também pode incluir o elemento padrão IE6 <! - [if lte IE 6]>. A propósito, qual navegador não suporta style = "width:%" ??
Amischiefr 11/08/09
Eu não sei como isso pode ser feito no lado do servidor, mas sim, algum javscript pode fazê-lo, mas eu quero evitá-lo, a menos que o css / html não possa fazê-lo
#
O que não pode. Portanto, se você deseja que ambos sejam dinâmicos, precisará fazê-lo no lado do script ou do servidor.
Amischiefr 12/08/2009