HTML / CSS: Rendre deux div flottants de la même hauteur

106

J'ai un petit problème particulier que je résous actuellement en utilisant un table, voir ci-dessous. Fondamentalement, je souhaite que deux div occupent 100% de la largeur disponible, mais n'occupent que l'espace vertical nécessaire (ce qui n'est pas vraiment évident sur la photo). Les deux devraient à tout moment avoir exactement la même hauteur avec une petite ligne entre eux, comme indiqué.

texte alternatif
(source: pici.se )

Tout cela est très facile à utiliser table, ce que je fais actuellement. Cependant, je ne suis pas trop intéressé par la solution, car sémantiquement, ce n'est pas réellement une table.

Deniz Dogan
la source
2
Euh ... où est la photo? Je sais que je suis trop tard pour commenter ça
Ajay Kulkarni

Réponses:

160

Vous pouvez obtenir des colonnes de hauteur égale en CSS en appliquant un remplissage inférieur d'une grande quantité, une marge négative inférieure du même montant et en entourant les colonnes d'un div qui a un dépassement caché. Centrer verticalement le texte est un peu plus délicat, mais cela devrait vous aider en cours de route.

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

Je pense qu'il vaut la peine de le mentionner la réponse précédente de streetpc a un code HTML invalide, le doctype est XHTML et il y a des guillemets simples autour des attributs. Il convient également de noter quevous n'avez pas besoin d'un élément supplémentaire avec clearon pour effacer les flotteurs internes du conteneur. Si vous utilisez overflow hidden, cela efface les flottants dans tous les navigateurs non-IE, puis ajoutez simplement quelque chose pour donner hasLayout tel que width ou zoom: 1 provoquera IE effacer ses floats internes.

J'ai testé cela dans tous les navigateurs modernes FF3 + Opera9 + Chrome Safari 3+ et IE6 / 7/8. Cela peut sembler un truc moche mais cela fonctionne bien et je l'utilise beaucoup en production.

J'espère que ça aide.

Natalie Downe
la source
1
Le code que j'ai donné valide au validateur du W3C (enfin, une fois que vous avez ajouté un élément <title>, ce qui n'était pas votre point). De plus, les spécifications permettent l'utilisation de guillemets simples selon cette discussion: sitepoint.com/forums/showthread.php?t=54273#6
instanceof me
1
Excuses, mon erreur. J'ai modifié ma réponse ci-dessus. Cependant, avec votre méthode, si la colonne de droite devient plus grande que la gauche, le rouge apparaît en dessous car les deux cases ne sont pas exactement à la bonne hauteur. En fonction de la conception, j'opterais pour des fausses colonnes ou cette méthode avec les marges inférieures et le rembourrage.
Natalie Downe
2
En fait, bien que la solution donnée par Kevin C. concernant la suppression des ombres fonctionne pour le rembourrage supérieur, gauche et droit, elle ne fonctionne pas pour le bas. Je n'ai pas trouvé de solution jusqu'à présent.
JeanMertz
1
Beau travail Natalie. @laarsk La hauteur imprévisible est exactement ce à quoi cela sert, n'est-ce pas? Voir la démo: jsfiddle.net/RT3MT/4 déplacez les paragraphes "plus longs" pour voir
jpillora
1
C'est l'un des hacks CSS les plus laids que j'ai jamais vu, mais je vais l'embrasser à bras ouverts lol. Cela semble être la seule voie à suivre
Matt Vukas
98

C'est l'année 2012 + n, donc si vous ne vous souciez plus d'IE6 / 7 display:table, display:table-rowet que vous display:table-celltravaillez dans tous les navigateurs modernes:

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

Mise à jour 17/06/2016: Si vous pensez que le temps est venu display:flex, consultez Flexbox Froggy .

Dmitry Leskov
la source
30
Quelle année sera-ce que cette réponse sera remplacée par display: flex?
LandonSchropp
12
Non, nous sommes maintenant en 2014 (;
Francisco Presencia
9
aaaaaa et c'est 2015 peut-être d'ici la fin de l'année, nous pouvons changer la réponse pour afficher: flex :)
MetalWeirdo
5
Je vis toujours dans les années 50.
Jay
1
Bonjour à partir de 2016! Nous pouvons utiliser flex maintenant
Brett Gregson
20

Vous devez utiliser flexbox pour y parvenir. Il n'est pas pris en charge dans IE8 et IE9 et uniquement avec le préfixe -ms dans IE10, mais tous les autres navigateurs le prennent en charge. Pour les préfixes de fournisseur, vous devez également utiliser un 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
la source
1
Le problème que j'ai avec flex est qu'il a besoin d'un wrapper autour des colonnes. Avec les floats + display: table technique je peux avoir par exemple un en-tête et un tas de colonnes et l'effet fonctionne sur les colonnes sans affecter l'en-tête.
Stijn de Witt
10

vous pouvez faire fonctionner cela avec js:

<script>
    $(document).ready(function() {
        var height = Math.max($("#left").height(), $("#right").height());
        $("#left").height(height);
        $("#right").height(height);
    });
</script>
Andi P. Trix
la source
1
Veuillez noter que cette question est déjà assez ancienne et que de meilleures solutions (sans avoir besoin de javascript) ont déjà été fournies.
nirazul le
1
J'aime vraiment cette solution. C'est amusant et montre que non seulement vous pouvez manipuler votre html avec css, mais que vous pouvez également le faire avec l'aide de jquery
csichar
6
Cette solution ne fonctionnera pas si la hauteur des colonnes change. Cela peut se produire si le contenu des colonnes est modifié. Cette fonction devrait être exécutée: lors du changement de contenu et du redimensionnement du navigateur. L'approche css est plus idéale car elle évite ces problèmes
alexreardon
5

C'est un problème classique en CSS. Il n'y a pas vraiment de solution à cela.

Cet article de A List Apart est une bonne lecture de ce problème. Il utilise une technique appelée «fausses colonnes», basée sur le fait d'avoir une image d'arrière-plan en mosaïque verticale sur l' élément contenant les colonnes, ce qui crée l'illusion de colonnes de longueur égale. Comme il se trouve sur le wrapper des éléments flottants, il est aussi long que l'élément le plus long.


Les éditeurs de A List Apart ont cette note sur l'article:

Note des éditeurs: Bien qu'excellent pour l'époque, cet article peut ne pas refléter les meilleures pratiques modernes.

La technique nécessite des conceptions de largeur complètement statiques qui ne fonctionnent pas bien avec les mises en page liquides et les techniques de conception réactive qui sont populaires aujourd'hui pour les sites multi-appareils. Pour les sites de largeur statique, cependant, c'est une option fiable.

Philippe Leybaert
la source
Merci, cela semble être un bon hack. Cependant, j'ai oublié de mentionner que la colonne de droite devrait contenir du texte, centré verticalement. Ai-je raison de croire que les fausses colonnes ne peuvent pas faire ça?
Deniz Dogan
4

J'ai eu un problème similaire et à mon avis, la meilleure option est d'utiliser juste un peu de javascript ou jquery.

Vous pouvez obtenir que les divs voulus aient la même hauteur en obtenant la valeur div la plus élevée et en appliquant cette valeur à tous les autres div. Si vous avez beaucoup de divs et de nombreuses solutions, je suggère d'écrire un petit code js avancé pour savoir lequel de tous les divs est le plus élevé, puis d'utiliser sa valeur.

Avec jquery et 2 divs, c'est très simple, voici un exemple de code:

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

Et pour la fin, il y a une dernière chose. Leur rembourrage (haut et bas) doit être le même! Si vous avez un rembourrage plus grand, vous devez éliminer la différence de rembourrage.

Monsieur Br
la source
1

Pour autant que je sache, vous ne pouvez pas faire cela en utilisant les implémentations actuelles de CSS. Pour créer deux colonnes, de hauteur égale, vous avez besoin de JS.

Calin Don
la source
1

Cela fonctionne pour moi dans IE 7, FF 3.5, Chrome 3b, Safari 4 (Windows).

Fonctionne également dans IE 6 si vous décommentez le div plus clair en bas. Edit : comme l'a dit Natalie Downe, vous pouvez simplement ajouter width: 100%;à la #containerplace.

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

Je ne connais pas de moyen CSS pour centrer verticalement le texte dans le bon div si le div n'est pas de hauteur fixe. Si c'est le cas, vous pouvez définir la line-heightmême valeur que la hauteur du div et mettre un div interne contenant votre texte avec display: inline; line-height: 110%.

exemple de moi
la source
1

En utilisant Javascript, vous pouvez faire en sorte que les deux balises div aient la même hauteur. Le plus petit div s'ajustera à la même hauteur que le plus grand tag div en utilisant le code ci-dessous:

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

Avec "gauche" et "droite" étant les identifiants des balises div.

Quintox303
la source
1

En utilisant la propriété 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>


la source
0

En utilisant JS, utilisez data-same-height="group_name"dans tous les éléments que vous souhaitez avoir la même hauteur .

L'exemple: https://jsfiddle.net/eoom2b82/

Le code:

$(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
la source
0

J'avais besoin de faire quelque chose de similaire, voici ma mise en œuvre. Pour récapituler le but, il est d'avoir 2 éléments occupant la largeur d'un conteneur parent donné, et la hauteur d'être seulement aussi haute que nécessaire. Essentiellement, la hauteur équivaut à la hauteur maximale de la plus grande quantité de contenu, mais l'autre conteneur est affleurant.

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%;
}
ce mec
la source
0

Il y a plusieurs années, la floatpropriété résolvait ce problème avec l' tableapproche utilisant display: table;et display: table-row;et display: table-cell;.

Mais maintenant, avec la propriété flex, vous pouvez le résoudre avec 3 lignes de code: display: flex;et flex-wrap: wrap;etflex: 1 0 50%;

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

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

1 0 50%sont les flexvaleurs que nous avons données à: flex-grow flex-shrink flex-basisrespectivement. C'est un raccourci relativement nouveau dans flexbox pour éviter de les taper individuellement. J'espère que cela aide quelqu'un là-bas

Fouad Boukredine
la source