HTML / CSS: fazendo dois divs flutuantes da mesma altura

106

Eu tenho um pequeno problema peculiar que estou resolvendo usando um table, veja abaixo. Basicamente, quero que dois divs ocupem 100% da largura disponível, mas ocupem apenas o espaço vertical necessário (o que não é tão óbvio na imagem). Os dois devem sempre ter exatamente a mesma altura com uma pequena linha entre eles, como mostrado.

texto alternativo
(fonte: pici.se )

Isso tudo é muito fácil de usar table, o que estou fazendo atualmente. No entanto, não estou muito interessado na solução, visto que semanticamente esta não é realmente uma tabela.

Deniz Dogan
fonte
2
Er ... onde está a foto? Eu sei que estou muito atrasado para comentar sobre isso
Ajay Kulkarni
Aqui está o link da imagem de WebArchive.org https://web.archive.org/web/20120617031534/http://pici.se/pictures/qJRMtoLPv.png
DidThis

Respostas:

160

Você pode obter colunas de altura igual em CSS aplicando preenchimento inferior de uma grande quantidade, margem negativa inferior da mesma quantidade e circundando as colunas com um div que possui overflow oculto. Centralizar o texto verticalmente é um pouco mais complicado, mas deve ajudá-lo no processo.

#container {
  overflow: hidden;
      width: 100%;
}
#left-col {
  float: left;
  width: 50%;
  background-color: orange;
  padding-bottom: 500em;
  margin-bottom: -500em;
}
#right-col {
  float: left;
  width: 50%;
  margin-right: -1px; /* Thank you IE */
  border-left: 1px solid black;
  background-color: red;
  padding-bottom: 500em;
  margin-bottom: -500em;
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

<head></head>

<body>
  <div id="container">
    <div id="left-col">
      <p>Test content</p>
      <p>longer</p>
    </div>
    <div id="right-col">
      <p>Test content</p>
    </div>
  </div>
</body>

Acho que vale a pena mencionar que a resposta anterior de streetpc tem html inválido, o doctype é XHTML e existem aspas simples em torno dos atributos. Também vale a pena notar quevocê não precisa de um elemento extra com clearon para limpar os flutuadores internos do contêiner. Se você usar overflow hidden, isso limpará os floats em todos os navegadores não-IE e, em seguida, apenas adicionar algo para fornecer hasLayout, como largura ou zoom: 1 fará com que o IE limpe seus floats internos.

Eu testei isso em todos os navegadores modernos FF3 + Opera9 + Chrome Safari 3+ e IE6 / 7/8. Pode parecer um truque feio, mas funciona bem e eu o uso muito na produção.

Eu espero que isso ajude.

Natalie Downe
fonte
1
O código que dei valida no validador do W3C (bem, uma vez que você adiciona um elemento <title>, que não era o seu ponto). Além disso, as especificações permitem o uso de aspas simples de acordo com esta discussão: sitepoint.com/forums/showthread.php?t=54273#6
instanceof me
1
Desculpas, erro meu. Eu alterei minha resposta acima. Aponte, porém, para observar, com seu método, se a coluna da direita ficar maior do que a da esquerda, o vermelho aparecerá na parte inferior, pois as duas caixas não têm exatamente a altura certa. Dependendo do projeto, eu optaria por colunas falsas ou este método com as margens inferiores e preenchimento.
Natalie Downe
2
Na verdade, embora a solução dada por Kevin C. sobre sombras sendo cortadas funcione para o preenchimento superior, esquerdo e direito, ela não funciona para o inferior. Não encontrei uma solução até agora.
JeanMertz
1
Bom trabalho, Natalie. @laarsk Altura imprevisível é exatamente para que serve, não é? Veja a demonstração: jsfiddle.net/RT3MT/4 mova os parágrafos "mais longos" para ver
jpillora
1
Este é um dos hacks de CSS mais feios que já vi, mas vou abraçá-lo de braços abertos lol. Parece ser o único caminho a seguir
Matt Vukas
98

É ano de 2012 + n, por isso, se você já não se preocupam com IE6 / 7, display:table, display:table-rowe display:table-celltrabalho em todos os navegadores modernos:

http://www.456bereastreet.com/archive/200405/equal_height_boxes_with_css/

Atualização 2016-06-17: Se você acha que chegou a hora display:flex, uma olhada no Flexbox Froggy .

Dmitry Leskov
fonte
30
Em que ano essa resposta será substituída display: flex?
LandonSchropp
12
Não, estamos agora em 2014 (;
Francisco Presencia
9
aaaaaaand é 2015 talvez até o final do ano possamos mudar a resposta para exibir: flex :)
MetalWeirdo 16/01/2015
5
Ainda estou morando na década de 1950.
Jay
1
Olá de 2016! Podemos usar o flex agora
Brett Gregson
20

Você deve usar o flexbox para fazer isso. Não é compatível com IE8 e IE9 e apenas com o prefixo -ms no IE10, mas todos os outros navegadores o suportam. Para prefixos de fornecedores, você também deve usar autoprefixer .

.parent {
    display: flex;
    flex-wrap: wrap; // allow wrapping items
}

.child {
    flex-grow: 1;
    flex-basis: 50%; // 50% for two in a row, 33% three in a row etc.
}
Luca Steeb
fonte
1
O problema que tenho com o flex é que ele precisa de um invólucro ao redor das colunas. Com a técnica floats + display: table, posso ter, por exemplo, um cabeçalho e um monte de colunas e o efeito funciona nas colunas sem afetar o cabeçalho.
Stijn de Witt
10

você pode fazer isso funcionar com js:

<script>
    $(document).ready(function() {
        var height = Math.max($("#left").height(), $("#right").height());
        $("#left").height(height);
        $("#right").height(height);
    });
</script>
Andi P. Trix
fonte
1
Observe que esta questão já é bastante antiga e soluções melhores (sem a necessidade de javascript) já foram fornecidas.
nirazul
1
Na verdade, gosto dessa solução. É divertido e mostra que você não só pode manipular seu html com css, mas também com a ajuda de jquery
csichar
6
Esta solução não funcionará se a altura das colunas mudar. Isso pode acontecer se o conteúdo das colunas for alterado. Esta função precisa ser executada: na mudança de conteúdo e no redimensionamento do navegador. A abordagem css é mais ideal, pois evita essas preocupações
alexreardon de
5

Este é um problema clássico em CSS. Não há realmente uma solução para isso.

Este artigo de A List Apart é uma boa leitura sobre esse problema. Ele usa uma técnica chamada "colunas falsas", baseada em ter uma imagem de fundo ladrilhada verticalmente no elemento que contém as colunas que cria a ilusão de colunas de comprimento igual. Como está no invólucro dos elementos flutuantes, é tão longo quanto o elemento mais longo.


Os editores A List Apart têm esta observação sobre o artigo:

Uma nota dos editores: embora excelente para a época, este artigo pode não refletir as melhores práticas modernas.

A técnica requer designs de largura completamente estáticos que não funcionam bem com layouts líquidos e técnicas de design responsivo que são populares hoje em sites de dispositivos cruzados. Para sites de largura estática, no entanto, é uma opção confiável.

Philippe Leybaert
fonte
Obrigado, parece um bom hack. No entanto, esqueci de mencionar que a coluna da direita deve conter texto centrado verticalmente. Estou certo em acreditar que colunas falsas não podem fazer isso?
Deniz Dogan
4

Tive problema semelhante e na minha opinião a melhor opção é usar um pouco de javascript ou jquery.

Você pode fazer com que os divs desejados tenham a mesma altura obtendo o maior valor de div e aplicando esse valor a todos os outros divs. Se você tiver muitos divs e muitas soluções, sugiro escrever um código js com pouco avanço para descobrir qual de todos os divs é o mais alto e, em seguida, usar seu valor.

Com jquery e 2 divs é muito simples, aqui está o código de exemplo:

$('.smaller-div').css('height',$('.higher-div').css('height'));

E para o final, há uma última coisa. O enchimento (superior e inferior) deve ser o mesmo! Se um tiver um preenchimento maior, você precisará eliminar a diferença de preenchimento.

Sr. Br
fonte
1

Pelo que eu sei, você não pode fazer isso usando as implementações atuais de CSS. Para fazer duas colunas de altura igual, você precisa de JS.

Calin Don
fonte
1

Isso funciona para mim no IE 7, FF 3.5, Chrome 3b, Safari 4 (Windows).

Também funciona no IE 6 se você remover o comentário do div mais claro na parte inferior. Edit : como Natalie Downe disse, você pode simplesmente adicionar width: 100%;em #containervez disso.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <style type="text/css">
        #container {
            overflow: hidden;
            border: 1px solid black;
            background-color: red;
        }
        #left-col {
            float: left;
            width: 50%;
            background-color: white;
        }
        #right-col {
            float: left;
            width: 50%;
            margin-right: -1px; /* Thank you IE */
        }
    </style>
</head>
<body>
    <div id='container'>
        <div id='left-col'>
            Test content<br />
            longer
        </div>
        <div id='right-col'>
            Test content
        </div>
        <!--div style='clear: both;'></div-->
    </div>
</body>
</html>

Não conheço uma maneira CSS de centralizar verticalmente o texto no div certo se o div não for de altura fixa. Se for, você pode definir o line-heightcom o mesmo valor da altura do div e colocar um div interno contendo seu texto com display: inline; line-height: 110%.

exemplo de mim
fonte
1

Usando Javascript, você pode fazer com que as duas tags div tenham a mesma altura. O div menor será ajustado para ter a mesma altura que a tag div mais alta usando o código mostrado abaixo:

var rightHeight = document.getElementById('right').clientHeight;
var leftHeight = document.getElementById('left').clientHeight;
if (leftHeight > rightHeight) {
document.getElementById('right').style.height=leftHeight+'px';
} else {
document.getElementById('left').style.height=rightHeight+'px';
}

Com "esquerda" e "direita" sendo os id das tags div.

Quintox303
fonte
1

Usando a propriedade css -> display: table-cell

div {
    border: 1px solid #000;
    margin: 5px;
    padding: 4px;
	display:table-cell;
	width:25%	;position:relative;
}
body{display:table;
	border-collapse:separate;
	border-spacing:5px 5px}
<div>
    This is my div one This is my div one This is my div one
</div>
<div>
    This is my div two This is my div two This is my div two This is my div two This is my div two This is my div two
</div>
<div>
    This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3 This is my div 3
</div>


fonte
0

Usando JS, use data-same-height="group_name"em todos os elementos que deseja que tenham a mesma altura .

O exemplo: https://jsfiddle.net/eoom2b82/

O código:

$(document).ready(function() {
    var equalize = function () {
        var disableOnMaxWidth = 0; // 767 for bootstrap

        var grouped = {};
        var elements = $('*[data-same-height]');

        elements.each(function () {
            var el = $(this);
            var id = el.attr('data-same-height');

            if (!grouped[id]) {
                grouped[id] = [];
            }

            grouped[id].push(el);
        });

        $.each(grouped, function (key) {
            var elements = $('*[data-same-height="' + key + '"]');

            elements.css('height', '');

            var winWidth = $(window).width();

            if (winWidth <= disableOnMaxWidth) {
                return;
            }

            var maxHeight = 0;

            elements.each(function () {
                var eleq = $(this);
                maxHeight = Math.max(eleq.height(), maxHeight);
            });

            elements.css('height', maxHeight + "px");
        });
    };

    var timeout = null;

    $(window).resize(function () {
        if (timeout) {
            clearTimeout(timeout);
            timeout = null;
        }

        timeout = setTimeout(equalize, 250);
    });
    equalize();
});
Wiliam
fonte
0

Eu precisava fazer algo semelhante, aqui está minha implementação. Para recapitular o propósito, é que 2 elementos ocupem a largura de um determinado contêiner pai e a altura seja tão alta quanto o necessário. Basicamente, a altura é igual à altura máxima da maior quantidade de conteúdo, mas o outro recipiente está nivelado.

html

<div id="ven">
<section>some content</section>
<section>some content</section>
</div>

css

#ven {
height: 100%;
}
#ven section {
width: 50%;
float: left;
height: 100%;
}
esse cara
fonte
0

Vários anos atrás, a floatpropriedade costumava resolver esse problema com a tableabordagem usando display: table;e display: table-row;e display: table-cell;.

Mas agora com a propriedade flex, você pode resolvê-lo com 3 linhas de código: display: flex;e flex-wrap: wrap;eflex: 1 0 50%;

.parent {
    display: flex;
    flex-wrap: wrap;
}

.child {
 // flex: flex-grow flex-shrink flex-basis;
    flex: 1 0 50%;
}

1 0 50%são os flexvalores que atribuímos a: flex-grow flex-shrink flex-basisrespectivamente. É um atalho relativamente novo no flexbox para evitar digitá-los individualmente. Eu espero que isto ajude alguém lá fora

Fouad Boukredine
fonte