Spraw, aby div (wysokość) zajmował pozostałą wysokość rodzica


108

http://jsfiddle.net/S8g4E/

Mam pojemnik divz dwójką dzieci. Pierwsze dziecko ma określony wzrost. Jak sprawić, aby drugie dziecko zajmowało „wolną przestrzeń” pojemnika divbez podawania określonej wysokości?

W tym przykładzie różowy divpowinien zajmować również białą przestrzeń.


Podobne do tego pytania: jak sprawić, by div zajmował pozostałą wysokość?

Ale nie chcę podawać pozycji absolutnej .


Próbowałem też, podając wzrost drugiego dziecka 100%, ale nie działa: jsfiddle.net/S8g4E/1
Alvaro

Odpowiedzi:


156

Rozszerzanie #downdziecka, aby wypełnić pozostałą przestrzeń, #containermożna osiągnąć na różne sposoby, w zależności od obsługi przeglądarki, którą chcesz osiągnąć i od tego, czy #upma określoną wysokość, czy nie .

Próbki

Krata

gridUkład CSS oferuje jeszcze jedną opcję, chociaż może nie być tak prosta jak model Flexbox. Jednak wymaga tylko stylizacji elementu kontenera:

.container { display: grid; grid-template-rows: 100px }

Plik grid-template-rowsWyznacza pierwszy wiersz w postaci stałej 100px wysokości i pozostają rzędy rozciągają się automatycznie wypełniając pozostałą przestrzeń.

Jestem prawie pewien, że IE11 wymaga -ms-prefiksów, więc upewnij się, że sprawdziłeś funkcjonalność w przeglądarkach, które chcesz obsługiwać.

Flexbox

Modułflexbox CSS3 Flexible Box Layout Module ( ) jest teraz dobrze obsługiwany i może być bardzo łatwy do wdrożenia. Ponieważ jest elastyczny, działa nawet wtedy, gdy #upnie ma określonej wysokości.

#container { display: flex; flex-direction: column; }
#down { flex-grow: 1; }

Ważne jest, aby pamiętać, że obsługa IE10 i IE11 dla niektórych właściwości flexboksa może być wadliwa, a IE9 lub starsze nie mają żadnej obsługi.

Obliczona wysokość

Innym łatwym rozwiązaniem jest użycie jednostki funkcjonalnej CSS3calc , jak wskazuje Alvaro w swojej odpowiedzi , ale wymaga, aby wzrost pierwszego dziecka był znaną wartością:

#up { height: 100px; }
#down { height: calc( 100% - 100px ); }

Jest dość szeroko obsługiwany, z jedynymi godnymi uwagi wyjątkami: <= IE8 lub Safari 5 (brak wsparcia) i IE9 (częściowe wsparcie). Niektóre inne problemy obejmują używanie programu calc w połączeniu z transform lub box-shadow , więc jeśli Cię to niepokoi, upewnij się, że wykonałeś test w wielu przeglądarkach.

Inne alternatywy

Jeśli potrzebne jest wsparcie starszych, można dodać height:100%;do #downuczyni różową div pełnej wysokości, z jednym zastrzeżeniem. Spowoduje to przepełnienie pojemnika, ponieważ #uppopycha go w dół.

Dlatego możesz dodać overflow: hidden;do kontenera, aby to naprawić.

Alternatywnie, jeśli wysokość #upjest stała, możesz umieścić ją całkowicie w pojemniku i dodać wyściółkę do #down.

A jeszcze inną opcją byłoby użycie wyświetlacza tabeli:

#container { width: 300px; height: 300px; border: 1px solid red; display: table;}
#up { background: green; display: table-row; height: 0; }
#down { background: pink; display: table-row;}​

4
Chciałbym, aby # dół miał # wysokość kontenera - # wysokość w górę. Więc ukryty przepełnienie nie jest tym, czego szukam. A także nie chcę używać pozycji bezwzględnej. Dzięki!
Alvaro

@Alvaro, dodałem kolejną opcję, używając wyświetlaczy tabelowych. Wadą jest tutaj kompatybilność. PS Element umieszczony absolutnie wewnątrz kontenera i position: relative;pozycjonuje go względem kontenera, a nie okna. To powinno być realną opcją.
użytkownik

2
Wiersz tabeli powinien działać dla Ciebie, zobacz ten jsFiddle, aby uzyskać dowód. Metoda pozycji bezwzględnej nie będzie w stanie dać takich samych wyników, jak te skrzypce, więc możemy usunąć to z listy (# w dół i #container będą miały taką samą wysokość w tym scenariuszu).
użytkownik

3
Dużo prosisz @Alvaro. CSS nie jest językiem skryptowym; nie potrafi obliczyć rzeczy. Utkniesz z iluzjami lub js.
Jezen Thomas

1
@Quantastical, dziękuję za pomoc, ale w swojej ostatniej edycji właśnie skopiowałeś odpowiedź, którą opublikowałem. Jakaś wzmianka o tym przynajmniej byłaby miła.
Alvaro

24

Minęły prawie dwa lata, odkąd zadałem to pytanie. Właśnie wymyśliłem css calc (), które rozwiązuje ten problem, który miałem i pomyślałem, że byłoby miło dodać go na wypadek, gdyby ktoś miał ten sam problem. (Nawiasem mówiąc, ostatecznie użyłem pozycji bezwzględnej).

http://jsfiddle.net/S8g4E/955/

Oto plik css

#up { height:80px;}
#down {
    height: calc(100% - 80px);//The upper div needs to have a fixed height, 80px in this case.
}

Więcej informacji na ten temat znajdziesz tutaj: http://css-tricks.com/a-couple-of-use-cases-for-calc/

Obsługa przeglądarek: http://caniuse.com/#feat=calc


1
Ja też używałem CSS3, calcgdzie obsługa szerokiej przeglądarki nie jest tak ważna (IE8 i starsze oraz Safari 5 nie obsługują tego).
użytkownik

3
Jakiś sposób zrobić coś podobnego z dynamiczną #upwysokością?
Adam Waite

@AdamWaite, z dynamiczną wysokością # up, będziesz chciał użyć rozwiązania przepełnienia opisanego w innej odpowiedzi.
użytkownik

5

Moja odpowiedź używa tylko CSS i nie używa overflow: hidden ani display: table-row. Wymaga to, aby pierwsze dziecko naprawdę miało określony wzrost, ale w swoim pytaniu stwierdzasz, że tylko drugie dziecko musi mieć nieokreślony wzrost, więc uważam, że powinieneś to zaakceptować.

html

<div id="container">
    <div id="up">Text<br />Text<br />Text<br /></div>
    <div id="down">Text<br />Text<br />Text<br /></div>
</div>

css

#container { width: 300px; height: 300px; border:1px solid red;}
#up { background: green; height: 63px; float:left; width: 100% }
#down { background:pink; padding-top: 63px; height: 100%; box-sizing: border-box; }

http://jsfiddle.net/S8g4E/288/


3

Abstrakcyjny

Nie znalazłem w pełni satysfakcjonującej odpowiedzi, więc musiałem sam się tego dowiedzieć.

Moje wymagania:

  • element powinien zajmować dokładnie pozostałą przestrzeń, albo gdy rozmiar jego zawartości jest mniejszy lub większy niż pozostały rozmiar przestrzeni (w drugim przypadku powinien być pokazany pasek przewijania );
  • rozwiązanie powinno działać, gdy wysokość rodzica jest obliczana , a nie określona ;
  • calc()nie należy używać, ponieważ pozostały element nie powinien nic wiedzieć o innych rozmiarach elementów;
  • Należy stosować nowoczesne i znane techniki projektowania, takie jak flexboxy .

Rozwiązanie

  • Zamień na flexboxy wszystkich bezpośrednich rodziców z obliczoną wysokością (jeśli istnieją) i następnego rodzica, którego wysokość jest określona ;
  • Określ flex-grow: 1dla wszystkich bezpośrednich rodziców z wyliczoną wysokością (jeśli istnieje) i elementem aby zajmowały całą pozostałą przestrzeń, gdy rozmiar zawartości elementu jest mniejszy;
  • Określ flex-shrink: 0dla wszystkich elementów elastycznych o stałej wysokości aby nie zmniejszyły się, gdy rozmiar zawartości elementu jest większy niż pozostały rozmiar przestrzeni;
  • Określ overflow: hiddendla wszystkich bezpośrednich rodziców z obliczoną wysokością (jeśli istnieje), aby wyłączyć przewijanie i zabronić wyświetlania zawartości przepełnienia;
  • Określ overflow: autodo elementu , aby umożliwić przewijanie wewnątrz niego.

JSFiddle (element ma bezpośrednich rodziców z wyliczoną wysokością)

JSFiddle (prosty przypadek: brak bezpośrednich rodziców z obliczoną wysokością)


2

sprawdź demo - http://jsfiddle.net/S8g4E/6/

użyj css -

#container { width: 300px; height: 300px; border:1px solid red; display: table;}
#up { background: green; display: table-row; }
#down { background:pink; display: table-row;}

Należy dodać height: 1pxdo, #upaby mieć pewność, że zajmuje minimalną wysokość. Oto obsługa przeglądarki dla display: table: caniuse.com/css-table
thirtydot.

Czy mógłbyś mi pokazać, jak można osiągnąć to rozwiązanie w tym „bardziej złożonym” przykładzie: jsfiddle.net/fyNX4 Dziękuję bardzo
Alvaro

2

Chyba że się nie rozumiem, możesz po prostu dodać height: 100%;i overflow:hidden;do #down.

#down { 
    background:pink; 
    height:100%; 
    overflow:hidden;
}​

DEMO na żywo

Edycja: ponieważ nie chcesz używać overflow:hidden;, możesz użyć display: table;w tym scenariuszu; jednak nie jest obsługiwany przed IE 8. ( display: table;wsparcie )

#container { 
    width: 300px; 
    height: 300px; 
    border:1px solid red;
    display:table;
}

#up { 
    background: green;
    display:table-row;
    height:0; 
}

#down { 
    background:pink;
    display:table-row;
}​

DEMO na żywo

Uwaga: Powiedziałeś, że chcesz, aby #downwysokość była równa #containerwysokości minus #upwysokość. display:table;Rozwiązanie robi dokładnie to i to jsfiddle wcieli że dość wyraźnie.


1
Nie chcę, aby # dół przekroczył wysokość # kontenera
Alvaro,

Właśnie to zauważyłem. Możesz dodać overflow:hiddendo, aby ukryć dodatkową zawartość.
Josh Mein

1
Skopiuję / wkleję to, co powiedziałem do MrSlayera: chciałbym, aby # dół miał # wysokość kontenera - # wysokość w górę. Więc ukryty przepełnienie nie jest tym, czego szukam. A także nie chcę używać pozycji bezwzględnej. Dzięki!
Alvaro

Problem polega na tym, że jeśli w przykładzie odwrócisz dwa elementy div, zielony element div znajduje się na zewnątrz.
środa,

To wcale nie odpowiada na pytanie. Mówi „Aby zająć całą pozostałą wysokość”, nawet jeśli zajmie całą pozostałą wysokość, nastąpi przepełnienie.
Giridhar Karnik

1

Możesz używać pływaków do wypychania zawartości w dół:

http://jsfiddle.net/S8g4E/5/

Masz kontener o stałym rozmiarze:

#container {
    width: 300px; height: 300px;
}

Treść może przepływać obok pływaka. O ile nie ustawimy pływaka na pełną szerokość:

#up {
    float: left;
    width: 100%;
}

Podczas gdy #upi #downudostępnij najwyższą pozycję, #downzawartość może zaczynać się tylko po dolnej części pływającej #up:

#down {
    height:100%;
}​

Zauważ, że #upfaktycznie obejmuje górną część #down: jsfiddle.net/thirtydot/S8g4E/9
thirtydot.

Tak, tak to działa. Ale jeśli OP nie potrzebuje zaokrąglonej ramki lub czegoś innego #up, to prawdopodobnie jest to akceptowalne.
biziclop,

To rozwiązanie jest bliskie, ale chciałbym, aby # dół miał # wysokość kontenera - # wysokość do góry. (W twoim rozwiązaniu # wysokość w dół = # wysokość kontenera). Dzięki ”
Alvaro,

1
@Alvaro: Dlaczego tak musi być? To rozwiązanie w większości przypadków wygląda poprawnie, nawet jeśli jest tylko złudzeniem.
thirtydot

Cóż, to pytanie jest uproszczonym przykładem z tego bardziej „złożonego” przykładu: jsfiddle.net/fyNX4 Nie zadziała, prawda?
Alvaro

-3

Nie jestem pewien, czy można to zrobić wyłącznie za pomocą CSS, chyba że czujesz się komfortowo w udawaniu iluzji. Może używać odpowiedź Josh mein, a zestaw #containerdooverflow:hidden .

Oto rozwiązanie jQuery:

var contH = $('#container').height(),
upH = $('#up').height();
$('#down').css('height' , contH - upH);

Dzięki, szukałem czystego rozwiązania CSS.
Alvaro
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.