HTML / CSS: creare due div flottanti della stessa altezza


106

Ho un piccolo problema particolare che attualmente risolvo usando a table, vedi sotto. Fondamentalmente, voglio che due div occupino il 100% della larghezza disponibile, ma occupino solo lo spazio verticale necessario (il che non è così ovvio dall'immagine). I due dovrebbero sempre avere esattamente la stessa altezza con una piccola linea tra loro, come mostrato.

testo alternativo
(fonte: pici.se )

È tutto molto facile da usare table, cosa che sto facendo attualmente. Tuttavia, non sono molto entusiasta della soluzione, poiché semanticamente questa non è effettivamente una tabella.


2
Ehm ... dov'è la foto? So che sono troppo tardi per commentare questo
Ajay Kulkarni

Risposte:


160

Puoi ottenere colonne di uguale altezza in CSS applicando una spaziatura interna inferiore di un importo elevato, un margine negativo inferiore della stessa quantità e circondando le colonne con un div che ha nascosto l'overflow. Centrare verticalmente il testo è un po 'più complicato, ma dovrebbe esserti d'aiuto.

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

Penso che valga la pena menzionarlo la risposta precedente di streetpc ha un html non valido, il doctype è XHTML e ci sono virgolette singole intorno agli attributi. Vale anche la pena notare chenon è necessario un elemento aggiuntivo con clearper cancellare i galleggianti interni del contenitore. Se usi l'overflow nascosto questo cancella i float in tutti i browser non IE e quindi aggiungi qualcosa per dare hasLayout come width o zoom: 1 farà sì che IE cancelli i suoi float interni.

L'ho testato in tutti i browser moderni FF3 + Opera9 + Chrome Safari 3+ e IE6 / 7/8. Può sembrare un brutto trucco ma funziona bene e lo uso molto in produzione.

Spero che aiuti.


1
Il codice che ho fornito viene convalidato dal validatore del W3C (beh, una volta aggiunto un elemento <title>, che non era il tuo punto). Inoltre, le specifiche consentono l'uso di virgolette singole secondo questa discussione: sitepoint.com/forums/showthread.php?t=54273#6
instanceof me

1
Mi scuso, errore mio. Ho modificato la mia risposta sopra. Tieni presente però, con il tuo metodo, se la colonna di destra diventa più grande della sinistra, il rosso viene mostrato sotto poiché le due caselle non sono esattamente della giusta altezza. A seconda del design, opterei per colonne finte o questo metodo con i margini inferiori e l'imbottitura.
Natalie Downe

2
In realtà, mentre la soluzione data da Kevin C. sulle ombre tagliate funziona per il riempimento superiore, sinistro e destro, non funziona per il fondo. Finora non ho trovato una soluzione.
JeanMertz

1
Bel lavoro Natalie. @laarsk L'altezza imprevedibile è esattamente a cosa serve, no? Guarda la demo: jsfiddle.net/RT3MT/4 sposta i paragrafi "più lunghi" per vederli
jpillora

1
Questo è uno dei più brutti hack CSS che abbia mai visto, ma lo abbraccerò a braccia aperte lol. Sembra essere l'unico modo per andare avanti
Matt Vukas

98

È l'anno 2012 + n, quindi se non ti interessa più IE6 / 7 display:table, display:table-rowe display:table-celllavori con tutti i browser moderni:

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

Aggiornamento 17/06/2016: se pensi che sia giunto il momento display:flex, dai un'occhiata a Flexbox Froggy .


30
Che anno sarà quando questa risposta verrà sostituita con display: flex?
LandonSchropp

12
No, ora siamo nel 2014 (;
Francisco Presencia

9
aaaaaa ed è il 2015 forse entro la fine dell'anno possiamo cambiare la risposta da visualizzare: flex :)
MetalWeirdo

5
Vivo ancora negli anni '50.
Jay

1
Ciao dal 2016! Possiamo usare il flex ora
Brett Gregson

20

Dovresti usare flexbox per ottenere questo risultato. Non è supportato in IE8 e IE9 e solo con il prefisso -ms in IE10, ma tutti gli altri browser lo supportano. Per i prefissi del fornitore, dovresti anche utilizzare il prefisso automatico .

.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.
}

1
Il problema che ho con flex è che necessita di un wrapper attorno alle colonne. Con la tecnica floats + display: table posso avere ad esempio un'intestazione e un gruppo di colonne e l'effetto funziona sulle colonne senza influire sull'intestazione.
Stijn de Witt

10

puoi farlo funzionare con js:

<script>
    $(document).ready(function() {
        var height = Math.max($("#left").height(), $("#right").height());
        $("#left").height(height);
        $("#right").height(height);
    });
</script>

1
Si noti che questa domanda è già piuttosto vecchia e sono già state fornite soluzioni migliori (senza la necessità di javascript).
nirazul

1
In realtà mi piace questa soluzione. È divertente e mostra che non solo puoi manipolare il tuo html con css, ma puoi anche farlo con l'aiuto di jquery
csichar

6
Questa soluzione non funzionerà se l'altezza delle colonne cambia. Ciò potrebbe accadere se il contenuto delle colonne viene modificato. Questa funzione dovrebbe essere eseguita: sulla modifica del contenuto e sul ridimensionamento del browser. L'approccio CSS è più ideale in quanto evita queste preoccupazioni
alexreardon

5

Questo è un classico problema nei CSS. Non c'è davvero una soluzione per questo.

Questo articolo di A List Apart è una buona lettura su questo problema. Utilizza una tecnica chiamata "colonne finte", basata sull'avere un'immagine di sfondo affiancata verticalmente sull'elemento contenente le colonne che crea l'illusione di colonne di uguale lunghezza. Poiché si trova sull'involucro degli elementi flottati, è lungo quanto l'elemento più lungo.


Gli editori di A List Apart hanno questa nota sull'articolo:

Nota della redazione: sebbene eccellente per l'epoca, questo articolo potrebbe non riflettere le migliori pratiche moderne.

La tecnica richiede progetti di larghezza completamente statici che non funzionano bene con i layout liquidi e le tecniche di progettazione reattiva che sono popolari oggi per i siti cross-device. Per i siti di larghezza statica, tuttavia, è un'opzione affidabile.


Grazie, sembra un bel trucco. Tuttavia, ho dimenticato di dire che la colonna di destra dovrebbe contenere del testo, centrato verticalmente. Ho ragione a credere che le finte colonne non possano farlo?
Deniz Dogan

4

Ho avuto un problema simile e secondo me l'opzione migliore è usare solo un po 'di javascript o jquery.

Puoi fare in modo che i div desiderati abbiano la stessa altezza ottenendo il valore div più alto e applicando quel valore a tutti gli altri div. Se hai molti div e molte soluzioni ti suggerisco di scrivere un codice js poco avanzato per scoprire quale di tutti i div è il più alto e quindi utilizzare il suo valore.

Con jquery e 2 div è molto semplice, ecco un esempio di codice:

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

E per la fine, c'è un'ultima cosa. La loro imbottitura (superiore e inferiore) deve essere la stessa! Se uno ha un'imbottitura più grande, è necessario eliminare la differenza di imbottitura.


1

Per quanto ne so, non puoi farlo utilizzando le attuali implementazioni di CSS. Per creare due colonne di uguale altezza è necessario JS.


1

Questo funziona per me in IE 7, FF 3.5, Chrome 3b, Safari 4 (Windows).

Funziona anche in IE 6 se rimuovi il commento dal div più chiaro in fondo. Modifica : come ha detto Natalie Downe, puoi semplicemente aggiungere width: 100%;a #container.

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

Non conosco un modo CSS per centrare verticalmente il testo nel div giusto se il div non è di altezza fissa. Se lo è, puoi impostare lo line-heightstesso valore dell'altezza del div e inserire un div interno contenente il tuo testo con display: inline; line-height: 110%.


1

Utilizzando Javascript, puoi fare in modo che i due tag div abbiano la stessa altezza. Il div più piccolo si adatterà alla stessa altezza del tag div più alto utilizzando il codice mostrato di seguito:

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 "left" e "right" che sono gli ID dei tag div.


1

Usando la proprietà 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>


0

Usando JS, usa data-same-height="group_name"in tutti gli elementi che vuoi avere la stessa altezza .

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

Il codice:

$(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();
});

0

Avevo bisogno di fare qualcosa di simile, ecco la mia implementazione. Per ricapitolare lo scopo, è di avere 2 elementi che occupano la larghezza di un dato contenitore genitore e l'altezza deve essere alta solo quanto deve essere. Essenzialmente l'altezza è uguale all'altezza massima della maggiore quantità di contenuto, ma l'altro contenitore è a filo.

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

0

Diversi anni fa, la floatproprietà risolveva quel problema con l' tableapproccio utilizzando display: table;e display: table-row;e display: table-cell;.

Ma ora con la proprietà flex, puoi risolverlo con 3 righe di codice: 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%sono i flexvalori a cui abbiamo dato: flex-grow flex-shrink flex-basisrispettivamente. È una scorciatoia relativamente nuova in flexbox per evitare di digitarli singolarmente. Spero che questo aiuti qualcuno là fuori

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.