Faire en sorte que div (hauteur) occupe la hauteur restante du parent

107

http://jsfiddle.net/S8g4E/

J'ai un conteneur divavec deux enfants. Le premier enfant a une taille donnée. Comment faire en sorte que le deuxième enfant occupe «l'espace libre» du conteneur divsans donner une hauteur précise?

Dans l'exemple, le rose divdoit également occuper l'espace blanc.


Similaire à cette question: Comment faire en sorte que div occupe la hauteur restante?

Mais je ne veux pas donner une position absolue .

Alvaro
la source
J'ai essayé aussi de donner la taille du deuxième enfant à 100% mais ne fonctionne pas: jsfiddle.net/S8g4E/1
Alvaro

Réponses:

156

L'extension de l' #downenfant pour remplir l'espace restant de #containerpeut être réalisée de différentes manières en fonction du support du navigateur que vous souhaitez atteindre et de sa #uphauteur définie ou non .

Échantillons

la grille

La gridmise en page de CSS offre encore une autre option, bien qu'elle ne soit pas aussi simple que le modèle Flexbox. Cependant, il suffit de styliser l'élément conteneur:

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

Le grid-template-rowsdéfinit la première ligne comme une hauteur fixe de 100 pixels, et les lignes restantes s'étirent automatiquement pour remplir l'espace restant.

Je suis presque sûr que IE11 nécessite des -ms-préfixes, alors assurez-vous de valider la fonctionnalité dans les navigateurs que vous souhaitez prendre en charge.

Flexbox

Le module de mise en page de boîte flexibleflexbox de CSS3 ( ) est maintenant bien pris en charge et peut être très facile à implémenter. Parce qu'il est flexible, il fonctionne même lorsqu'il #upn'a pas de hauteur définie.

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

Il est important de noter que la prise en charge d'IE10 et d'IE11 pour certaines propriétés de la flexbox peut être boguée, et IE9 ou une version antérieure n'a aucune prise en charge.

Hauteur calculée

Une autre solution simple consiste à utiliser l' unité fonctionnelle CSS3calc , comme le souligne Alvaro dans sa réponse , mais cela nécessite que la hauteur du premier enfant soit une valeur connue:

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

Il est assez largement pris en charge, les seules exceptions notables étant <= IE8 ou Safari 5 (pas de support) et IE9 (support partiel). Certains autres problèmes incluent l'utilisation de calc en conjonction avec transform ou box-shadow , alors assurez-vous de tester dans plusieurs navigateurs si cela vous concerne.

Autres alternatives

Si un support plus ancien est nécessaire, vous pouvez ajouter height:100%;pour #downrendre le div rose pleine hauteur, avec une mise en garde. Cela provoquera un débordement du conteneur, car #upil le pousse vers le bas.

Par conséquent, vous pouvez ajouter overflow: hidden;au conteneur pour résoudre ce problème.

Sinon, si la hauteur de #upest fixe, vous pouvez le positionner de manière absolue dans le conteneur et ajouter un haut de remplissage à #down.

Et, encore une autre option serait d'utiliser un affichage de table:

#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;}​
utilisateur
la source
4
Je voudrais que #down ait #container height - #up height. Donc, le débordement caché n'est pas ce que je recherche. Et je ne veux pas non plus utiliser la position absolue. Merci!
Alvaro
@Alvaro, j'ai ajouté une autre option, en utilisant des affichages de table. L'inconvénient ici est la compatibilité. PS Un élément positionné absolument à l'intérieur d'un conteneur avec le position: relative;positionne par rapport au conteneur, pas à la fenêtre. Donc, cela devrait être une option viable.
utilisateur
2
Table-row devrait fonctionner pour vous, voyez ce jsFiddle pour la preuve. La méthode de position absolue ne pourra pas donner les mêmes résultats que ce violon, nous pouvons donc rayer cela de la liste (#down et #container auront la même hauteur dans ce scénario).
utilisateur
3
Vous demandez beaucoup, @Alvaro. CSS n'est pas un langage de script; il ne peut pas calculer les choses. Vous êtes coincé avec des illusions ou des js.
Jezen Thomas
1
@Quantastical, merci pour votre aide, mais dans votre dernière modification, vous venez de copier la réponse que j'ai publiée. Certains en parler au moins serait bien.
Alvaro
24

Cela fait presque deux ans que j'ai posé cette question. Je viens de trouver css calc () qui résout ce problème que j'avais et j'ai pensé que ce serait bien de l'ajouter au cas où quelqu'un aurait le même problème. (Au fait, j'ai fini par utiliser la position absolue).

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

Voici le css

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

Et plus d'informations à ce sujet ici: http://css-tricks.com/a-couple-of-use-cases-for-calc/

Prise en charge du navigateur: http://caniuse.com/#feat=calc

Alvaro
la source
1
Moi aussi, j'utilise CSS3 calcoù la prise en charge des navigateurs étendus n'est pas aussi importante (IE8 et les versions antérieures et Safari 5 ne la prennent pas en charge).
utilisateur
3
Une façon de faire la même chose avec une #uphauteur dynamique ?
Adam Waite
@AdamWaite, avec une hauteur #up dynamique, vous voudrez utiliser la solution de débordement décrite dans l'autre réponse.
utilisateur
5

Ma réponse n'utilise que CSS, et elle n'utilise pas overflow: hidden ou display: table-row. Cela exige que le premier enfant ait vraiment une taille donnée, mais dans votre question, vous indiquez que seul le deuxième enfant doit avoir sa taille non spécifiée, donc je pense que vous devriez trouver cela acceptable.

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/

TWR Cole
la source
2

consultez la démo - http://jsfiddle.net/S8g4E/6/

utiliser css -

#container { width: 300px; height: 300px; border:1px solid red; display: table;}
#up { background: green; display: table-row; }
#down { background:pink; display: table-row;}
Dipak
la source
Vous devez ajouter height: 1pxà #uppour vous assurer qu'il prend la quantité minimale de hauteur. Voici le support du navigateur pour display: table: caniuse.com/css-table
thirtydot
Pourriez-vous s'il vous plaît me montrer comment cette solution peut être obtenue dans cet exemple "plus complexe", s'il vous plaît: jsfiddle.net/fyNX4 Merci beaucoup
Alvaro
2

À moins que je comprends mal, vous pouvez simplement ajouter height: 100%;et overflow:hidden;à #down.

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

DÉMO en direct

Edit: Puisque vous ne souhaitez pas utiliser overflow:hidden;, vous pouvez utiliser display: table;pour ce scénario; cependant, il n'est pas pris en charge avant IE 8. ( display: table;prise en charge )

#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;
}​

DÉMO en direct

Remarque: vous avez dit que vous vouliez que la #downhauteur soit la #containerhauteur moins la #uphauteur. La display:table;solution fait exactement cela et ce jsfiddle le représentera assez clairement.

Josh Mein
la source
1
Je ne veux pas que #down dépasse la hauteur de #container
Alvaro
Je viens de le remarquer. Vous pouvez ajouter overflow:hiddenà pour masquer le contenu supplémentaire.
Josh Mein
1
Je vais copier / coller ce que j'ai dit à MrSlayer: je voudrais que #down ait #container height - #up height. Donc, le débordement caché n'est pas ce que je recherche. Et je ne veux pas non plus utiliser la position absolue. Merci!
Alvaro
Le problème avec ceci est que si vous inversez les deux divs dans votre exemple, le div vert est à l'extérieur.
Ced
Cela ne répond pas du tout à la question. Il indique "Pour occuper toute la hauteur restante", même si cela occupe toute la hauteur restante, il y aura un débordement.
Giridhar Karnik
2

Abstrait

Je n'ai pas trouvé de réponse pleinement satisfaisante, j'ai donc dû la découvrir moi-même.

Mes exigences:

  • l'élément doit prendre exactement l'espace restant lorsque la taille de son contenu est plus petite ou plus grande que la taille de l'espace restant (dans le second cas, la barre de défilement doit être affichée );
  • la solution devrait fonctionner lorsque la hauteur du parent est calculée et non spécifiée ;
  • calc()ne doit pas être utilisé car l'élément restant ne doit rien savoir sur une autre taille d'élément;
  • une technique de mise en page moderne et familière telle que les boîtes flexibles doit être utilisée.

La solution

  • Transforme en flexbox tous les parents directs avec la hauteur calculée (le cas échéant) et le parent suivant dont la hauteur est spécifiée ;
  • Spécifiez flex-grow: 1à tous les parents directs avec la hauteur calculée (le cas échéant) et l'élément afin qu'ils occupent tout l'espace restant lorsque la taille du contenu de l'élément est plus petite;
  • Spécifiez flex-shrink: 0à tous les éléments flexibles avec une hauteur fixe afin qu'ils ne deviennent pas plus petits lorsque la taille du contenu de l'élément est plus grande que la taille de l'espace restant;
  • Spécifiez overflow: hiddenà tous les parents directs avec la hauteur calculée (le cas échéant) pour désactiver le défilement et interdire l'affichage du contenu de débordement;
  • Indiquez overflow: autoà l'élément pour permettre le défilement à l' intérieur.

JSFiddle (l'élément a des parents directs avec une hauteur calculée)

JSFiddle (cas simple: pas de parents directs avec hauteur calculée)

N. Kudryavtsev
la source
1

Vous pouvez utiliser des flotteurs pour pousser le contenu vers le bas:

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

Vous disposez d'un conteneur de taille fixe:

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

Le contenu est autorisé à circuler à côté d'un flotteur. Sauf si nous définissons le flotteur sur toute la largeur:

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

Alors que #upet #downpartagez la position supérieure, #downle contenu de ne peut commencer qu'après le bas du flottant #up:

#down {
    height:100%;
}​
biziclop
la source
Notez que #upcouvre en fait la partie supérieure de #down: jsfiddle.net/thirtydot/S8g4E/9
thirtydot
Oui, c'est comme ça que ça marche. Mais si OP n'a pas besoin d'une bordure arrondie ou de quelque chose d'autre #up, alors c'est probablement acceptable.
biziclop
Cette solution est proche, mais je voudrais que #down ait #container height - #up height. (Dans votre solution #down height = #container height). Merci '
Alvaro
1
@Alvaro: Pourquoi faut-il que ce soit comme ça? Cette solution semble correcte dans la plupart des cas, même si ce n'est qu'une illusion.
thirtydot
Eh bien, cette question est un exemple simplifié de cet exemple plus "complexe": jsfiddle.net/fyNX4 Cela ne fonctionnerait pas, non?
Alvaro
-3

Je ne suis pas sûr que cela puisse être fait uniquement avec CSS, à moins que vous ne soyez à l'aise pour le simuler avec des illusions. Peut-être utiliser la réponse de Josh Mein et régler #containersur overflow:hidden.

Pour ce que ça vaut, voici une solution jQuery:

var contH = $('#container').height(),
upH = $('#up').height();
$('#down').css('height' , contH - upH);
Jezen Thomas
la source
Merci, je cherchais une solution pure Css.
Alvaro