HTML / CSS: nadanie dwóch pływających elementów div o tej samej wysokości


106

Mam trochę osobliwy problem, który obecnie rozwiązuję za pomocą table, patrz poniżej. Zasadniczo chcę, aby dwa elementy div zajmowały 100% dostępnej szerokości, ale zajmowały tylko tyle miejsca w pionie, ile potrzeba (co nie jest tak oczywiste na rysunku). Obydwa powinny zawsze mieć dokładnie tę samą wysokość z niewielką linią między nimi, jak pokazano.

tekst alternatywny
(źródło: pici.se )

To wszystko jest bardzo łatwe do zrobienia przy użyciu table, co obecnie robię. Nie jestem jednak zbytnio zainteresowany rozwiązaniem, ponieważ semantycznie nie jest to w rzeczywistości tabela.


2
Eee ... gdzie jest zdjęcie? Wiem, że jestem za późno, by to skomentować
Ajay Kulkarni

Odpowiedzi:


160

Możesz uzyskać kolumny o równej wysokości w CSS, stosując dolne wypełnienie dużej ilości, dolny ujemny margines o tej samej wartości i otaczając kolumny elementem div, który ma ukryte przepełnienie. Wyśrodkowanie tekstu w pionie jest trochę trudniejsze, ale powinno ci to pomóc.

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

Myślę, że warto o tym wspomnieć poprzednia odpowiedź Streetpc ma nieprawidłowy html, typ dokumentu to XHTML, a atrybuty są otoczone pojedynczymi cudzysłowami. Warto również to zauważyćnie potrzebujesz dodatkowego elementu przy clearwłączonym, aby wyczyścić wewnętrzne pływaki pojemnika. Jeśli użyjesz przepełnienia ukrytego, wyczyści to elementy pływające we wszystkich przeglądarkach innych niż IE, a następnie po prostu dodasz coś, co ma dać hasLayout, takie jak szerokość lub powiększenie: 1 spowoduje, że IE wyczyści swoje wewnętrzne elementy pływające.

Przetestowałem to we wszystkich nowoczesnych przeglądarkach FF3 + Opera9 + Chrome Safari 3+ i IE6 / 7/8. Może się to wydawać brzydką sztuczką, ale działa dobrze i często go używam w produkcji.

Mam nadzieję, że to pomoże.


1
Kod, który podałem, sprawdza walidację w walidatorze W3C (cóż, po dodaniu elementu <title>, o co nie chodziło). Ponadto specyfikacje pozwalają na użycie pojedynczych cudzysłowów zgodnie z tą dyskusją: sitepoint.com/forums/showthread.php?t=54273#6
instanceof me

1
Przepraszam, mój błąd. Poprawiłem powyższą odpowiedź. Zwróć jednak uwagę, że w twojej metodzie, jeśli prawa kolumna staje się większa niż lewa, czerwony prześwituje pod spodem, ponieważ dwa pola nie mają dokładnie odpowiedniej wysokości. W zależności od projektu wybrałbym fałszywe kolumny lub tę metodę z dolnymi marginesami i dopełnieniem.
Natalie Downe

2
W rzeczywistości, chociaż rozwiązanie podane przez Kevina C. dotyczące odcinania cieni działa w przypadku wypełnienia górnego, lewego i prawego, nie działa w przypadku dołu. Jak dotąd nie znalazłem rozwiązania.
JeanMertz

1
Niezła robota Natalie. @laarsk Nieprzewidywalna wysokość jest dokładnie tym, do czego to służy, prawda? Zobacz demo: jsfiddle.net/RT3MT/4 przesuń „dłuższe” akapity dookoła, aby zobaczyć
jpillora

1
To jeden z najbrzydszych hacków CSS, jakie kiedykolwiek widziałem, ale zamierzam go ogarnąć z otwartymi ramionami lol. Wydaje się, że to jedyna droga naprzód
Matt Vukas

98

Jest rok 2012 + n, więc jeśli nie troska o IE6 / 7 display:table, display:table-rowa display:table-cellpraca we wszystkich nowoczesnych przeglądarek:

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

Aktualizacja 17.06.2016: Jeśli myślisz, że nadszedł czas display:flex, sprawdź Flexbox Froggy .


30
Jaki będzie rok, kiedy ta odpowiedź zostanie zastąpiona display: flex?
LandonSchropp

12
Nie, mamy teraz 2014 rok (;
Francisco Presencia,

9
aaaaaa i już 2015 może do końca roku zmienić odpowiedź na: flex :)
MetalWeirdo

5
Nadal żyję w latach pięćdziesiątych.
Jay

1
Witam od 2016 roku! Możemy teraz używać flexa
Brett Gregson

20

Aby to osiągnąć, powinieneś użyć flexbox. Nie jest obsługiwany w IE8 i IE9 i tylko z prefiksem -ms w IE10, ale wszystkie inne przeglądarki go obsługują. W przypadku prefiksów dostawców należy również użyć autoprefiksera .

.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
Problem, który mam z fleksem polega na tym, że potrzebuje on otoki wokół kolumn. Dzięki technice floats + display: table mogę mieć np. Nagłówek i kilka kolumn, a efekt działa na kolumnach bez wpływu na nagłówek.
Stijn de Witt

10

możesz to uzyskać pracując z js:

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

1
Proszę zauważyć, że to pytanie jest już dość stare i lepsze rozwiązania (bez potrzeby javascript) zostały już dostarczone.
nirazul

1
Właściwie podoba mi się to rozwiązanie. To jest zabawa i pokazuje, że nie tylko można manipulować HTML z CSS, ale można też zrobić to za pomocą jQuery
csichar

6
To rozwiązanie nie zadziała, jeśli zmieni się wysokość kolumn. Może się to zdarzyć, jeśli zawartość kolumn zostanie zmieniona. Ta funkcja musiałaby zostać uruchomiona: przy zmianie treści i zmianie rozmiaru przeglądarki. Podejście CSS jest bardziej idealne, ponieważ pozwala uniknąć tych problemów
alexreardon

5

To klasyczny problem w CSS. Naprawdę nie ma na to rozwiązania.

Ten artykuł z A List Apart to dobra lektura na ten problem. Wykorzystuje technikę zwaną „fałszywymi kolumnami”, polegającą na umieszczeniu jednego obrazu tła ułożonego pionowo na elemencie zawierającym kolumny, co tworzy iluzję kolumn o równej długości. Ponieważ znajduje się na owijce elementów pływających, jest tak długi, jak najdłuższy element.


Redaktorzy A List Apart mają w artykule następującą uwagę:

Uwaga od redaktorów: artykuł ten, choć doskonały jak na swoje czasy, może nie odzwierciedlać współczesnych najlepszych praktyk.

Technika ta wymaga projektów o całkowicie statycznej szerokości, które nie działają dobrze z układami płynnymi i elastycznymi technikami projektowania, które są obecnie popularne w witrynach obsługujących różne urządzenia. Jednak w przypadku witryn o statycznej szerokości jest to niezawodna opcja.


Dziękuję, to wygląda na niezły hack. Jednak zapomniałem wspomnieć, że prawa kolumna powinna zawierać tekst, wyśrodkowany w pionie. Czy mam rację wierząc, że fałszywe kolumny nie mogą tego zrobić?
Deniz Dogan

4

Miałem podobny problem i moim zdaniem najlepszą opcją jest użycie trochę javascript lub jquery.

Możesz uzyskać tę samą wysokość, aby pożądane elementy DIV miały taką samą wysokość, uzyskując najwyższą wartość i stosując ją do wszystkich innych elementów div. Jeśli masz wiele elementów div i wiele rozwiązań, sugeruję napisanie niewielkiego zaawansowanego kodu js, aby dowiedzieć się, który ze wszystkich elementów div jest najwyższy, a następnie użyć jego wartości.

Z jquery i 2 divami jest to bardzo proste, oto przykładowy kod:

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

I na koniec ostatnia rzecz. Ich wypełnienie (góra i dół) muszą być takie same! Jeśli ktoś ma większe wypełnienie, musisz wyeliminować różnicę wypełnienia.


1

O ile wiem, nie można tego zrobić przy użyciu obecnych implementacji CSS. Aby utworzyć dwie kolumny o równej wysokości, potrzebujesz JS.


1

To działa dla mnie w IE 7, FF 3.5, Chrome 3b, Safari 4 (Windows).

Działa również w IE 6, jeśli odkomentujesz wyraźniejszy element div na dole. Edit : jak Natalie Downe powiedział, można po prostu dodać width: 100%;do #containerzamiast.

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

Nie znam sposobu CSS na wyśrodkowanie w pionie tekstu w prawym elemencie div, jeśli element div nie ma stałej wysokości. Jeśli tak, możesz ustawić tę line-heightsamą wartość co wysokość div i wstawić wewnętrzny div zawierający tekst za pomocą display: inline; line-height: 110%.


1

Używając JavaScript, możesz ustawić dwa znaczniki DIV na tę samą wysokość. Mniejszy element div zostanie dopasowany do tej samej wysokości, co najwyższy znacznik div, używając kodu pokazanego poniżej:

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

Z „left” i „right” są identyfikatorami tagów div.


1

Używając właściwości 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

Używając JS, użyj data-same-height="group_name"we wszystkich elementach, które chcesz mieć taką samą wysokość .

Przykład: https://jsfiddle.net/eoom2b82/

Kod:

$(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

Musiałem zrobić coś podobnego, oto moja realizacja. Podsumowując, chodzi o to, aby dwa elementy zajmowały szerokość danego kontenera nadrzędnego, a wysokość była tak wysoka, jak to konieczne. Zasadniczo wysokość równa maksymalnej wysokości największej ilości zawartości, ale drugi pojemnik jest równy.

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

Kilka lat temu, floatnieruchomość wykorzystywana do rozwiązania tego problemu z tablepodejściem użyciu display: table;i display: table-row;i display: table-cell;.

Ale teraz, dzięki właściwości flex, możesz rozwiązać to za pomocą 3 linii kodu: display: flex;i flex-wrap: wrap;iflex: 1 0 50%;

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

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

1 0 50%to flexwartości, którym nadaliśmy: flex-grow flex-shrink flex-basisodpowiednio. Jest to stosunkowo nowy skrót w flexboksie, aby uniknąć wpisywania ich indywidualnie. Mam nadzieję, że to komuś pomoże

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.