Enfant à l'intérieur du parent avec hauteur minimale: 100% n'héritant pas de la hauteur

167

J'ai trouvé un moyen de créer un conteneur div pour occuper au moins toute la hauteur d'une page, en définissant min-height: 100%;. Cependant, lorsque j'ajoute un div imbriqué et un ensemble height: 100%;, il ne s'étire pas à la hauteur du conteneur. Y a-t-il un moyen de le réparer?

html, body {
  height: 100%;
  margin: 0;
}

#containment {
  min-height: 100%;
  background: pink;
}

#containment-shadow-left {
  height: 100%;
  background: aqua;
}
<div id="containment">
  <div id="containment-shadow-left">
    Hello World!
  </div>
</div>

boiteux
la source
27
Solution moderne: donner le récipient display:flexet flex-direction:columnet donner à l'enfant flex:1.
jackocnr
3
@jackocnr Cela ne fonctionne dans aucun IE en raison d'un bogue , il a été corrigé dans Edge.
Autocollants du

Réponses:

146

Il s'agit d'un bug Webkit (chrome / safari) signalé, les enfants de parents avec min-height ne peuvent pas hériter de la propriété height: https://bugs.webkit.org/show_bug.cgi?id=26559

Apparemment, Firefox est également affecté (impossible de tester dans IE pour le moment)

Solution de contournement possible:

  • ajouter une position: par rapport à #containment
  • ajouter la position: absolue à # contenir-ombre-gauche

Le bogue ne s'affiche pas lorsque l'élément interne a un positionnement absolu.

Voir http://jsfiddle.net/xrebB/

Edit le 10 avril 2014

Comme je travaille actuellement sur un projet pour lequel j'ai vraiment besoin de conteneurs parents min-heightet d'éléments enfants héritant de la hauteur du conteneur, j'ai fait quelques recherches supplémentaires.

Premièrement: je ne sais plus si le comportement actuel du navigateur est vraiment un bogue. Les spécifications CSS2.1 disent:

Le pourcentage est calculé par rapport à la hauteur du bloc contenant de la boîte générée. Si la hauteur du bloc conteneur n'est pas spécifiée explicitement (c'est-à-dire qu'elle dépend de la hauteur du contenu) et que cet élément n'est pas positionné de manière absolue, la valeur est calculée sur «auto».

Si je mets une hauteur min sur mon conteneur, je ne spécifie pas explicitement sa hauteur - donc mon élément devrait avoir une autohauteur. Et c'est exactement ce que Webkit - et tous les autres navigateurs - font.

Deuxièmement, la solution de contournement que j'ai trouvée:

Si je règle mon élément conteneur display:tableavec, height:inheritil agit exactement de la même manière que si je lui donnais un min-height100%. Et - plus important encore - si j'y display:table-cellattribue l' élément enfant, il héritera parfaitement de la hauteur de l'élément conteneur - qu'il soit de 100% ou plus.

CSS complet:

html, body {
  height: 100%;
  margin: 0;
}

#container {
  background: green;
  display: table;
  height: inherit;
  width: 100%;
}

#content {
  background: red;
  display: table-cell;
}

Le balisage:

<div id="container">
  <div id="content">
      <p>content</p>
  </div>
</div>

Voir http://jsfiddle.net/xrebB/54/ .

ptriek
la source
27
Mec, ce n'est toujours pas réglé: S
Mārtiņš Briedis
Oui, ce n'est pas - je vois qu'il y a quelques correctifs, mais à partir de Chrome 29, il n'affiche toujours pas le comportement attendu. Cependant, cela ne fonctionne pas non plus dans Firefox 23, IE 10, Safari 5 ou Opera 12. Au moins tous les navigateurs sont d'accord ...
Paul d'Aoust
3
C'est une lecture étrange de la spécification pour conclure que la hauteur min / max n'est pas explicite ... et par étrange je veux dire faux. En lisant tout le paragraphe, dans son contexte, cette interprétation est incorrecte. Pour clarifier pourquoi, «hauteur du bloc conteneur», dans son contexte, est sémantiquement différente de la propriété height. Si à la place, le phrasé était " propriété de hauteur du bloc contenant" alors Votre interprétation aurait un sens (et serait un bogue dans la spécification).
WraithKenny
1
Nous sommes en 2019. Nous avons raté 10 ans de ce bug. La solution flex a fonctionné pour moi stackoverflow.com/questions/8468066/…
Ilya Chernov
6
Je suis de l'ère du verrouillage
David Callanan
174

Ajouter height: 1pxau conteneur parent. Fonctionne dans Chrome, FF, Safari.

Kushagra Gour
la source
8
Cela ne résout pas le problème, en fait, vous remplacez le réglage de hauteur min: 100% qui n'obtient rien qui ne puisse être atteint avec la hauteur: 100%, ce qui n'est pas ce que veut l'OP
styler
16
L'ajout de @styler height: 1px;ne remplacera pas la hauteur min. Plutôt l'inverse. C'est la meilleure solution ici ... démo: jsbin.com/mosaboyo/1/edit
jjenzz
2
Voir ceci pour savoir pourquoi height: 1px;fonctionne stackoverflow.com/questions/2341821/height100-vs-min-height100
Ben Alavi
31
@jjenzz Le problème avec ceci, que je pense que styler essayait de comprendre, est que cela ne conserve pas le trait d'expansion de min-height. Par exemple, s'il y a suffisamment de texte, il débordera. Voir jsbin.com/vuyapitizo/1
binaryfunt
3
Citant le commentaire de Paul ci-dessous: "Mais cela ne permet pas au conteneur de grandir, ce qui va à l'encontre de l'objectif d'utiliser min-height." stackoverflow.com/questions/8468066/…
Leo Lei
103

J'ai pensé que je partagerais ceci, car je ne l'ai vu nulle part, et c'est ce que j'ai utilisé pour résoudre ma solution.

SOLUTION :min-height: inherit;

J'avais un parent avec une taille minimale spécifiée, et j'avais besoin d'un enfant qui soit également de cette taille.

.parent {
  min-height: 300px;
  background-color: rgba(255,255,0,0.5); //yellow
}

.child {
  min-height: inherit;
  background-color: rgba(0,255,0,0.5); //blue
}

p {
  padding: 20px;
  color: red;
  font-family: sans-serif;
  font-weight: bold;
  text-align: center;
}
<div class="parent">
  <div class="child">
    <p>Yellow + Blue = Green :)</p>
  </div>
</div>

De cette façon, l'enfant agit maintenant comme hauteur 100% de la hauteur min.

J'espère que certaines personnes trouveront cela utile :)

Kevin Upton
la source
9
Fonctionne partiellement, mais l'enfant n'hérite que du fichier min-height. Lorsque la taille des parents est plus grande, l'enfant ne se développe pas.
OguzGelal
1
Vous avez sauvé ma vie
casamia
6
Cela ne fonctionne que lorsque la hauteur minimale est absolue, et non en pourcentage, AFAICS.
Benjamin
4
Fonctionne également très bien si le parent a une valeur vh! MERCI!
user1658080
1
Ne convient pas à toutes les situations mais parfois très utile. Merci!
Blackbam
15

Cela a été ajouté dans un commentaire de @jackocnr mais je l'ai manqué. Pour les navigateurs modernes, je pense que c'est la meilleure approche.

Cela oblige l'élément interne à remplir tout le conteneur s'il est trop petit, mais augmente la hauteur du conteneur s'il est trop grand.

#containment {
  min-height: 100%;
  display: flex;
  flex-direction: column;
}

#containment-shadow-left {
  flex: 1;
}
JW.
la source
1
c'est le meilleur car la flexbox est largement compatible.
Jose Carlos Ramírez Vásquez
8

La solution de Kushagra Gour fonctionne (au moins dans Chrome et IE) et résout le problème d'origine sans avoir à utiliser display: table;et display: table-cell;. Voir plunker: http://plnkr.co/edit/ULEgY1FDCsk8yiRTfOWU

Le réglage min-height: 100%; height: 1px;sur le div externe entraîne sa hauteur réelle à au moins 100%, selon les besoins. Cela permet également au div interne d'hériter correctement de la hauteur.

Jeremy Hewett
la source
23
Mais cela ne permet pas au conteneur de se développer, ce qui va à l'encontre de l'objectif d'utiliser la hauteur minimale.
Sal le
J'avais également besoin d'un wrapper pour remplir la hauteur minimale et la hauteur du parent. Ce qui a fonctionné pour moi a été de définir la hauteur minimale pour hériter et la hauteur à 100%.
M. Duhart
6

En plus des réponses existantes, il existe également des unités de fenêtre vhà utiliser. Extrait simple ci-dessous. Bien sûr, il peut également être utilisé avec calc(), par exemple, min-height: calc(100vh - 200px);lorsque l'en-tête et le pied de page ont une 200pxhauteur ensemble.

body {
  margin: 0;
}

.child {
  min-height: 100vh;
  background: pink;
}
<div class="parent">
  <div class="child"></div>
</div>

Autocollants
la source
3

Je ne pense pas que ce soit un bug avec les navigateurs. Tous se comportent de la même manière - c'est-à-dire qu'une fois que vous arrêtez de spécifier des hauteurs explicites, min-height est fondamentalement une "dernière étape".

Il semble que ce soit exactement ce que suggère la spécification CSS 2.1: http://www.w3.org/TR/CSS2/visudet.html#the-height-property

Le pourcentage est calculé par rapport à la hauteur du bloc contenant de la boîte générée. Si la hauteur du bloc conteneur n'est pas spécifiée explicitement (c'est-à-dire qu'elle dépend de la hauteur du contenu) et que cet élément n'est pas positionné de manière absolue, la valeur est calculée sur «auto».

Par conséquent, comme le min-heightparent n'a pas de heightjeu de propriétés explicite , la valeur par défaut est auto.

Il existe des moyens de contourner ce display: table-cellproblème, éventuellement en utilisant des styles plus récents tels que flexbox, si cela est possible pour les navigateurs de votre public cible. Vous pouvez également contourner ce dans certaines situations en utilisant le topetbottom propriétés sur un élément intérieur positionné de manière absolue, ce qui vous donne une hauteur de 100% sans le spécifier.

Mike Hopkins
la source
3

Bien que cela display: flex;ait été suggéré ici, pensez à l'utiliser display: grid;maintenant qu'il est largement pris en charge . Par défaut, le seul enfant d'une grille remplira entièrement son parent.

html, body {
  height: 100%;
  margin: 0;
  padding: 0; /* Don't forget Safari */
}

#containment {
  display: grid;
  min-height: 100%;
  background: pink;
}

#containment-shadow-left {
  background: aqua;
}

Distorsion
la source
2

Pour les googleurs:

Cette solution de contournement jquery permet à #containment d'obtenir une hauteur automatiquement (par, height: auto), puis obtient la hauteur réelle affectée en tant que valeur de pixel.

<script type="text/javascript">
<!--
    $(function () {

        // workaround for webkit-bug http://stackoverflow.com/a/8468131/348841

        var rz = function () {
            $('#containment')
            .css('height', 'auto')
            .css('height', $('#containment').height() + 'px');
        };

        $(window).resize(function () {
            rz();
        });

        rz();

    })
-->
</script>
Jonas Stensved
la source
Belle solution de contournement, vous pouvez simplement définir la hauteur minimale de l'élément, sans définir la hauteur sur «auto». Cela a fonctionné pour moi.
Salvatore Zappalà
2

Le meilleur moyen d'y parvenir de nos jours est d'utiliser display: flex;. Cependant, vous pourriez rencontrer un problème en essayant de prendre en charge IE11. Selon https://caniuse.com utilisant flexbox:

IE 11 n'aligne pas verticalement les éléments correctement lorsque la hauteur minimale est utilisée

Solution compatible Internet Explorer

La solution consiste à utiliser display: table;sur le parent et display: table-row;sur l'enfant à la fois height: 100%;en remplacement de min-height: 100%;.

La plupart des solutions présentées ici utilisent display: table, table-rowet / ou table-cell, mais ils ne se reproduisent pas le même comportement que min-height: 100%;, ce qui est la suivante :

  • Hérite de la hauteur calculée du parent (par opposition à l'héritage de son height propriété);
  • Permettre à la taille du parent de dépasser son min-height;

Lors de l'utilisation de cette solution, le comportement est le même et la propriété min-heightn'est pas nécessaire ce qui permet de contourner le bogue.

Explication

La raison pour laquelle cela fonctionne est que, contrairement à la plupart des éléments, les éléments utilisent display: tableet table-rowseront toujours aussi hauts que leur contenu. Cela fait que leur heightpropriété se comporte de la même manière que min-height.

Solution en action

html, body {
  height: 100px;
  margin: 0;
}

#containment {
  display: table;
  height: 100%;
  background: pink;
  width: 100%;
}

#containment-shadow-left {
  display: table-row;
  height: 100%;
  background: aqua;
}

#content {
  padding: 15px;
}

#demo {
  display: none;
  background-color: red;
  height: 200px;
}

#demo-checkbox:checked ~ #demo {
  display: block;
}
<div id="containment">
  <div id="containment-shadow-left">
    <div id="content">
      <input id="demo-checkbox" type="checkbox">
      <label for="demo-checkbox">Click here for overflow demo</label>
      <div id="demo">This is taller than #containment</div>
    </div>
  </div>
</div>

Simon Martineau
la source
1

Une autre solution JS, qui est facile et peut être utilisée pour éviter une solution CSS uniquement non facile ou une solution de balisage / piratage supplémentaire.

function minHeight(elm, percent) {
  var windowHeight = isNaN(window.innerHeight) ? 
                     window.clientHeight : window.innerHeight;
  var height = windowHeight * percent / 100;
  elm.style.minHeight = height + 'px';
}

W / jQuery:

function minHeight($elm, percent) {
  var windowHeight = $(window).height();
  var height = windowHeight * percent / 100;
  $elm.css('min-height', height + 'px');
}

Directive angulaire:

myModule.directive('minHeight', ['$window', function($window) {
  return {
    restrict: 'A',
    link: function(scope, elm, attrs) {
      var windowHeight = isNaN($window.innerHeight) ? 
               $window.clientHeight : $window.innerHeight;
      var height = windowHeight * attrs.minHeight / 100;
      elm.css('min-height', height + 'px');
    }
  };
}]);

A utiliser comme ceci:

<div>
  <!-- height auto here -->
  <div min-height="100">
    <!-- This guy is at least 100% of window height but grows if needed -->
  </div>
</div>
Pandaiolo
la source
Merci pour la solution directive. C'est ce que j'ai fini par utiliser mais je ne voulais pas que la hauteur de la fenêtre soit la min; je voulais plutôt hériter de la hauteur min. du parent donc j'ai changé le code en ceci: var height = elm.parent () [0] .offsetHeight;
Sal le
1

Cela fonctionne généralement pour moi:


.parent {
  min-height: 100px;
  background-color: green;
  display: flex;
}
.child {
  height: inherit;
  width: 100%;
  background-color: red;
}
<!DOCTYPE html>
<html>
  <body>
    <div class="parent">
      <div class="child">
      </div>
    </div>
  </body>
</html>

la source
0

Juste pour garder ce sujet complet, j'ai trouvé une solution non explorée ici en utilisant la position fixe.

Pas de débordement

html, body, .wrapper, .parent, .child {
  position: fixed;
  top: 0; 
  bottom: 0;
  left: 0;
  right: 0;
  margin: 0;
  padding: 0;
  height: 100%;
}

.child {
  overflow: auto;
  background: gray;
}

.height-50 {
  height: 50%;
  width: 5em;
  margin: 10px auto;
  background: cyan;
}
<div class="wrapper">
  <div class="parent">
    <div class="child">
      
      <div class="height-50"></div>
      
    </div>
  </div>
</div>

Avec débordement

html, body, .wrapper, .parent, .child {
  position: fixed;
  top: 0; 
  bottom: 0;
  left: 0;
  right: 0;
  margin: 0;
  padding: 0;
  height: 100%;
}

.child {
  overflow: auto;
  background: gray;
}

.height-150 {
  height: 150%;
  width: 5em;
  margin: 10px auto;
  background: cyan;
}
<div class="wrapper">
  <div class="parent">
    <div class="child">
      
      <div class="height-150"></div>
      
    </div>
  </div>
</div>

Arthur
la source
-2

C'est ce qui fonctionne pour moi avec la taille basée sur le pourcentage et le parent grandissant toujours en fonction de la taille des enfants. Fonctionne bien dans Firefox, Chrome et Safari.

.parent {
  position: relative;
  min-height: 100%;
}

.child {
  min-height: 100vh;
}
<div class="parent">
    <div class="child"></div>
  </div>

Skoua
la source
-3

après avoir essayé le nôtre! chrome comprend que je veux que l'élément enfant ait une hauteur de 100% lorsque je règle la valeur d'affichage sur un bloc en ligne. btw réglage float le provoquera.

display:inline-block

mettre à jour

cela ne fonctionne pas. la solution est d'obtenir l'offsetheight du nœud parent et de l'utiliser au niveau et de la page avec javascript.

<script>
    SomedivElement = document.getElementById('mydiv');
    SomedivElement.style.height = String(nvleft.parentNode.offsetHeight) + 'px';    
</script>
Coban
la source