HTML / CSS: hacer que dos divs flotantes tengan la misma altura

106

Tengo un pequeño problema peculiar que actualmente resuelvo usando a table, ver más abajo. Básicamente, quiero que dos divs ocupen el 100% del ancho disponible, pero solo ocupen tanto espacio vertical como sea necesario (lo que no es tan obvio en la imagen). Los dos deben tener en todo momento exactamente la misma altura con una pequeña línea entre ellos, como se muestra.

texto alternativo
(fuente: pici.se )

Todo esto es muy fácil de usar table, lo que estoy haciendo actualmente. Sin embargo, no estoy muy interesado en la solución, ya que semánticamente no se trata de una tabla.

Deniz Dogan
fuente
2
Er ... ¿dónde está la foto? Sé que llego demasiado tarde para comentar sobre esto
Ajay Kulkarni
Aquí está el enlace de la imagen de WebArchive.org https://web.archive.org/web/20120617031534/http://pici.se/pictures/qJRMtoLPv.png
DidThis

Respuestas:

160

Puede obtener columnas de igual altura en CSS aplicando un relleno inferior de una gran cantidad, un margen negativo inferior de la misma cantidad y rodeando las columnas con un div que tiene un desbordamiento oculto. Centrar verticalmente el texto es un poco más complicado, pero esto debería ayudarte en el camino.

#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>

Creo que vale la pena mencionar que la respuesta anterior de streetpc tiene un html no válido, el tipo de documento es XHTML y hay comillas simples alrededor de los atributos. También vale la pena señalar queno necesita un elemento adicional con clearel fin de limpiar los flotadores internos del contenedor. Si usa overflow hidden, esto borra los flotantes en todos los navegadores que no son de IE y luego simplemente agregando algo para dar hasLayout como ancho o zoom: 1 hará que IE borre sus flotantes internos.

He probado esto en todos los navegadores modernos FF3 + Opera9 + Chrome Safari 3+ e IE6 / 7/8. Puede parecer un truco feo pero funciona bien y lo uso mucho en producción.

Espero que esto ayude.

Natalie Downe
fuente
1
El código que le di se valida en el validador de W3C (bueno, una vez que agrega un elemento <title>, que no era su punto). Además, las especificaciones permiten el uso de comillas simples de acuerdo con esta discusión: sitepoint.com/forums/showthread.php?t=54273#6
instanceof me
1
Disculpas, mi error. He modificado mi respuesta anterior. Sin embargo, tenga en cuenta que, con su método, si la columna de la derecha se vuelve más grande que la izquierda, el rojo se muestra debajo, ya que los dos cuadros no tienen exactamente la altura correcta. Dependiendo del diseño, optaría por columnas falsas o este método con los márgenes inferiores y el relleno.
Natalie Downe
2
En realidad, aunque la solución dada por Kevin C. sobre el corte de sombras funciona para el relleno superior, izquierdo y derecho, no funciona para el fondo. No he encontrado una solución hasta ahora.
JeanMertz
1
Buen trabajo Natalie. @laarsk La altura impredecible es exactamente para lo que es esto, ¿no? Ver demostración: jsfiddle.net/RT3MT/4 mueva los párrafos "más largos" para verlos
jpillora
1
Este es uno de los hacks de CSS más feos que he visto, pero lo aceptaré con los brazos abiertos. Parece ser el único camino a seguir
Matt Vukas
98

Es el año 2012 + n, por lo que si ya no le importa IE6 / 7 display:table, display:table-rowy display:table-celltrabaja en todos los navegadores modernos:

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

Actualización 2016-06-17: Si crees que ha llegado el momento display:flex, echa un vistazo a Flexbox Froggy .

Dmitry Leskov
fuente
30
¿Qué año será cuando se reemplace esta respuesta display: flex?
LandonSchropp
12
No, ahora estamos en 2014 (;
Francisco Presencia
9
aaaaaa y es 2015 tal vez para fin de año podamos cambiar la respuesta para mostrar: flex :)
MetalWeirdo
5
Todavía vivo en la década de 1950.
Jay
1
¡Hola desde 2016! Podemos usar flex ahora
Brett Gregson
20

Deberías usar flexbox para lograr esto. No es compatible con IE8 e IE9 y solo con el prefijo -ms en IE10, pero todos los demás navegadores lo admiten. Para los prefijos de proveedores, también debe 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
fuente
1
El problema que tengo con flex es que necesita un envoltorio alrededor de las columnas. Con la técnica de flotadores + visualización: tabla puedo tener, por ejemplo, un encabezado y un montón de columnas y el efecto funciona en las columnas sin afectar el encabezado.
Stijn de Witt
10

puedes hacer que esto funcione con js:

<script>
    $(document).ready(function() {
        var height = Math.max($("#left").height(), $("#right").height());
        $("#left").height(height);
        $("#right").height(height);
    });
</script>
Andi P. Trix
fuente
1
Tenga en cuenta que esta pregunta ya es bastante antigua y que ya se han proporcionado mejores soluciones (sin la necesidad de javascript).
nirazul
1
De hecho, me gusta esta solución. Es divertido y muestra que no solo puedes manipular tu html con css, sino que también puedes hacerlo con la ayuda de jquery
csichar
6
Esta solución no funcionará si cambia la altura de las columnas. Esto podría suceder si se cambia el contenido de las columnas. Esta función debería ejecutarse: al cambiar el contenido y al cambiar el tamaño del navegador. El enfoque CSS es más ideal ya que evita estas preocupaciones
alexreardon
5

Este es un problema clásico en CSS. Realmente no hay una solución para esto.

Este artículo de A List Apart es una buena lectura sobre este problema. Utiliza una técnica llamada "columnas falsas", basada en tener una imagen de fondo en mosaico vertical en el elemento que contiene las columnas que crea la ilusión de columnas de igual longitud. Dado que está en la envoltura de los elementos flotantes, es tan largo como el elemento más largo.


Los editores de A List Apart tienen esta nota en el artículo:

Una nota de los editores: si bien es excelente para su época, es posible que este artículo no refleje las mejores prácticas modernas.

La técnica requiere diseños de ancho completamente estáticos que no funcionan bien con los diseños líquidos y las técnicas de diseño receptivo que son populares hoy en día para los sitios multidispositivo. Sin embargo, para sitios de ancho estático, es una opción confiable.

Philippe Leybaert
fuente
Gracias, parece un buen truco. Sin embargo, olvidé mencionar que la columna de la derecha debe tener texto, centrado verticalmente. ¿Estoy en lo cierto al creer que las columnas falsas no pueden hacer esto?
Deniz Dogan
4

Tuve un problema similar y, en mi opinión, la mejor opción es usar solo un poco de javascript o jquery.

Puede conseguir que los divs deseados tengan la misma altura obteniendo el valor div más alto y aplicando ese valor a todos los demás divs. Si tiene muchos divs y muchas soluciones, sugiero escribir un pequeño código js avanzado para averiguar cuál de todos los divs es el más alto y luego usar su valor.

Con jquery y 2 divs es muy simple, aquí hay un código de ejemplo:

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

Y para el final, hay una última cosa. ¡Su relleno (superior e inferior) debe ser el mismo! Si uno tiene un relleno más grande, debe eliminar la diferencia de relleno.

Sr. Br
fuente
1

Hasta donde yo sé, no puede hacer esto usando implementaciones actuales de CSS. Para hacer dos columnas, de igual altura, necesita JS.

Calin Don
fuente
1

Esto me funciona en IE 7, FF 3.5, Chrome 3b, Safari 4 (Windows).

También funciona en IE 6 si descomenta el div más claro en la parte inferior. Editar : como dijo Natalie Downe, simplemente puede agregar width: 100%;en su #containerlugar.

<!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>

No conozco una forma CSS de centrar verticalmente el texto en el div correcto si el div no tiene una altura fija. Si es así, puede establecer el line-heightmismo valor que la altura del div y poner un div interno que contenga su texto con display: inline; line-height: 110%.

instancia de mi
fuente
1

Con Javascript, puede hacer que las dos etiquetas div tengan la misma altura. El div más pequeño se ajustará para tener la misma altura que la etiqueta div más alta usando el código que se muestra a continuación:

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

Con "izquierda" y "derecha" siendo las identificaciones de las etiquetas div.

Quintox303
fuente
1

Al usar la propiedad 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>


fuente
0

Usando JS, use data-same-height="group_name"en todos los elementos que desee que tengan la misma altura .

El ejemplo: https://jsfiddle.net/eoom2b82/

El 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
fuente
0

Necesitaba hacer algo similar, aquí está mi implementación. Para recapitular el propósito, es tener 2 elementos que ocupen el ancho de un contenedor principal dado, y que la altura solo sea tan alta como sea necesario. Básicamente, la altura es igual a la altura máxima de la mayor cantidad de contenido, pero el otro contenedor está al ras.

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%;
}
este chico
fuente
0

Hace varios años, la floatpropiedad solía resolver ese problema con el tableenfoque usando display: table;y display: table-row;y display: table-cell;.

Pero ahora con la propiedad flex, puedes resolverlo con 3 líneas de código: display: flex;y flex-wrap: wrap;yflex: 1 0 50%;

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

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

1 0 50%son los flexvalores que le dimos a: flex-grow flex-shrink flex-basisrespectivamente. Es un atajo relativamente nuevo en flexbox para evitar escribirlos individualmente. Espero que esto ayude a alguien

Fouad Boukredine
fuente