Comment forcer l'enfant div à 100% de la taille du parent div sans spécifier la taille du parent?


535

J'ai un site avec la structure suivante:

<div id="header"></div>

<div id="main">
  <div id="navigation"></div>
  <div id="content"></div>
</div>

<div id="footer"></div>

La navigation est à gauche et la div de contenu est à droite. Les informations pour la div de contenu sont extraites via PHP, donc elles sont différentes à chaque fois.

Comment puis-je redimensionner la navigation verticalement afin que sa hauteur soit la même que la hauteur de la div de contenu, quelle que soit la page chargée?


1
Utilisez le tableau d'affichage sur le parent et le tableau d'affichage sur l'enfant. Cela rendra l'enfant aussi longtemps que le parent l'est. Voir stackoverflow.com/q/22712489/3429430
user31782

3
Vous pouvez simplement définir display: flex; align-items: stretch;le div # main. Et ne pas utiliser height: 100%pour le contenu div #
Igor

Réponses:


167

REMARQUE : cette réponse s'applique aux navigateurs hérités sans prise en charge de la norme Flexbox. Pour une approche moderne, voir: https://stackoverflow.com/a/23300532/1155721


Je vous suggère de jeter un œil aux colonnes de hauteur égale avec CSS Cross-Browser et No Hacks .

Fondamentalement, faire cela avec CSS d'une manière compatible avec un navigateur n'est pas trivial (mais trivial avec des tables), alors trouvez-vous une solution pré-packagée appropriée.

En outre, la réponse varie selon que vous souhaitez une hauteur de 100% ou une hauteur égale. Habituellement, c'est la même hauteur. Si c'est 100% de hauteur, la réponse est légèrement différente.


7
Cela ressemble à une bonne solution jusqu'à ce que vous dessiniez une bordure, border:1px solid bluepar exemple sur container2: la bordure bleue se trouve sur les deux premières colonnes, pas seulement sur la deuxième colonne comme vous vous y attendiez.
Julien Kronegg

@bfritz, une meilleure solution serait d'utiliserdisplay:table
Siler

538

Pour le parent:

display: flex;

Vous devez ajouter quelques préfixes, http://css-tricks.com/using-flexbox/ .

Edit: Comme l'a noté @Adam Garner, align-items: stretch; n'est pas nécessaire. Son utilisation est également destinée aux parents, pas aux enfants. Si vous souhaitez définir l'étirement des enfants, vous utilisez align-self.

.parent {
  background: red;
  padding: 10px;
  display:flex;
}

.other-child {
  width: 100px;
  background: yellow;
  height: 150px;
  padding: .5rem;
}

.child {  
  width: 100px;
  background: blue;
}
<div class="parent">
  <div class="other-child">
    Only used for stretching the parent
  </div>
  <div class="child"></div>
</div>


3
IE11 ne fonctionne pas bien avec la flexbox et les hauteurs. cliquez sur "problèmes connus" ici: caniuse.com/#feat=flexbox
adamdport

@SuperUberDuper Eh bien, vous pouvez l'utiliser dans le bootstrap comme ceci: jsfiddle.net/prdwaynk Mais si j'étais vous, j'utiliserais une fondation qui est prête pour la production avec flexbox: foundation.zurb.com/sites/docs/xy-grid.html BS4 aura également Flexbox, mais il est toujours en alpha, et je pense que la fondation est meilleure de toute façon.
Aiphee

4
Si vous utilisez align-items: centeralors l'article dont vous avez besoin pour étirer vos besoinsalign-self: normal
Dominic

2
Ce n'est pas une bonne réponse, car cela doit définir la hauteur des parents. La question disait "sans préciser la taille du parent?".
SkuraZZ

3
@Aiphee downvoting car il semble que vous n'ayez pas vu la partie sur le fait de ne pas avoir à définir la hauteur des parents juste là dans le texte de la question d'origine, et pourtant votre "solution" fait exactement cela.
tylérisme

99

C'est un problème frustrant qui est constamment traité par les concepteurs. L'astuce est que vous devez définir la hauteur à 100% sur BODY et HTML dans votre CSS.

html,body {
    height:100%;
}

Ce code apparemment inutile est de définir pour le navigateur ce que signifie 100%. Frustrant, oui, mais c'est le moyen le plus simple.


9
Sauf que cela ne fonctionne pas toujours, par exemple si vous avez un élément positionné relatif à l'intérieur d'un élément positionné absolu, il ne force plus hasLayout.
Tim

En outre, si vous voulez vous débarrasser de la barre de défilement sur le côté droit de la fenêtre (apparaît dans Firefox v28), donner la fenêtre une bouffée d'oxygène: html { height: 100%; } body { height: 98%; }.
Chris Middleton

59
Cela ne fonctionne que si tous les parents ont une hauteur de 100%, il ne suffit pas de définir uniquement le html et le corps, tous les parents doivent avoir une hauteur définie.
RaduM

97

Je trouve que la définition des deux colonnes au display: table-cell;lieu de float: left;fonctionne bien.


10
La SEP elle-même ne le supporte plus, si cela aide quelqu'un à convaincre ses clients ...
Heraldmonkey

4
Ce devrait être la réponse acceptée. Les temps ont changé, cette réponse fonctionne dans tous les navigateurs (avec une petite bizarrerie dans Safari 5.1.17). Deux lignes de CSS et vous obtenez instantanément l'effet que vous recherchez sans aucun inconvénient auquel je peux penser.
callmetwan

7
Hissez cette réponse. Mettez-y le dos, les gars!

C'est la meilleure réponse. Oui, nous pouvons faire un tableau pour ce faire, mais ce ne sont pas des données tabulaires, au lieu de cela, nous traitons les divs comme si elles étaient des cellules de tableau ... Génial!
Derokorian

Cela m'a en fait mis dans la bonne direction pour un scénario différent. Dans le cas où quelqu'un a du mal à travailler avec des divs carrés qui sont également des conteneurs flexibles dans Firefox ou Edge, n'oubliez pas de définir l'élément: before pour afficher: table. Ne me demandez pas pourquoi mais ça le corrige.
CGodo

56

Si cela ne vous dérange pas que la division de navigation soit coupée en cas de division de contenu courte de manière inattendue, il existe au moins un moyen simple:

#main {
position: relative;
}

#main #navigation {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 10em; /* or whatever */
}

#main #content {
margin: 0;
margin-left: 10em; /* or whatever width you set for #navigation */
}

Sinon, il y a la technique des fausses colonnes .


2
Merci beaucoup, vous m'avez sauvé la journée. Je ne savais pas que l'on pouvait définir à la fois haut et bas et cela fonctionnerait de cette façon.
rubish

Cela fera que le contenu du conteneur cessera de le redimensionner.
DreamWave

+1 car il répond spécifiquement à la question du PO "Comment forcer la division enfant à 100% de la division parent sans spécifier la taille du parent?" Mon problème ne nécessitait pas de colonnes (qui sont mentionnées dans le détail de la question mais pas dans le titre principal) mais plutôt une div derrière l'autre. Cette réponse fonctionne dans les deux applications.
Luke

Ce devrait être la réponse choisie
Gabriel

32
#main {
    overflow: hidden;
}
#navigation, #content {
    margin-bottom: -1000px;
    padding-bottom: 1000px;
}

Je dois dire que je cherchais ce genre de solution. C'est simple et tellement évident que personne ne l'a compris. Félicitations @Roman!
Greg0ry

15

en utilisant jQuery:

$(function() {
    function unifyHeights() {
        var maxHeight = 0;
        $('#container').children('#navigation, #content').each(function() {
            var height = $(this).outerHeight();
            // alert(height);
            if ( height > maxHeight ) {
                maxHeight = height;
            }
        });
        $('#navigation, #content').css('height', maxHeight);
    }
    unifyHeights();
});

19
Math.max()serait votre ami ici.
alex

1
Impossible de faire fonctionner le CSS dans tous les cas pour moi et j'avais juste besoin d'une solution rapide. Ce n'est peut-être pas l' approche la plus standard , mais cela a très bien fonctionné. Merci! : -]

1
Lorsque vous utilisez la cssfonction de JQuery , vous ne pouvez pas faire la différence entre les supports d'écran et d'impression, comme vous le faites habituellement lorsque vous utilisez des solutions CSS pures. Ainsi, vous pouvez rencontrer des problèmes d'impression.
Julien Kronegg

12

Essayez de rendre la marge inférieure à 100%.

margin-bottom: 100%;

6
ou rembourrage en bas: 100%; ce n'est pas précis mais ça marche bien dans certaines situations.
Jason

padding-bottom fait l'affaire dans mon cas. Cette solution est très similaire à celle publiée par @Roman Kuntyi.
Greg0ry

10
#main {
   display: table;
} 
#navigation, #content {
   display: table-cell;
}

Regardez cet exemple .


C'est exactement ce que je faisais, je voulais ajouter une réponse. J'utilisais aussi height: 100%mais il s'est avéré que ce n'était pas nécessaire.
jcubic du

9

height : <percent>ne fonctionnera que si vous avez tous les nœuds parents avec un pourcentage de hauteur spécifié avec une hauteur fixe en pixels, ems, etc. au niveau supérieur. De cette façon, la hauteur descendra en cascade jusqu'à votre élément.

Vous pouvez spécifier 100% aux éléments html et body comme @Travis l'a indiqué précédemment pour que la hauteur de la page tombe en cascade vers vos nœuds.


9

Après de longues recherches et essais, rien n'a résolu mon problème sauf

style = "height:100%;"

sur les enfants div

et pour les parents appliquer ceci

.parent {
    display: flex;
    flex-direction: column;
}

aussi, j'utilise bootstrap et cela n'a pas corrompu le responsive pour moi.


1
J'ai dû retirer flex-direction: column;pour que cela fonctionne pour moi.
Richard Hedges

6

Basé sur la méthode décrite dans cet article j'ai créé une solution dynamique .Moins:

Html:

<div id="container3">
    <div id="container2">
        <div id="container1">
            <div id="col1">Column 1</div>
            <div id="col2">Column 2</div>
            <div id="col3">Column 3</div>
        </div>
    </div>
</div>

Moins:

/* Changes these variables to adjust your columns */
@col1Width: 60%;
@col2Width: 1%;
@padding: 0%;

/* Misc variable. Do not change */
@col3Width: 100% - @col1Width - @col2Width;

#container3 {
    float: left;
    width: 100%;
    overflow: hidden;
    background-color: red;
    position: relative;

    #container2 {
        float: left;
        width: 100%;
        position: relative;
        background-color: yellow;
        right: @col3Width;

        #container1 {
            float: left;
            width: 100%;
            position: relative;
            right: @col2Width;
            background-color: green;

            #col1 {
                float: left;
                width: @col1Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding;
                overflow: hidden;
            }

            .col2 {
                float: left;
                width: @col2Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 2;
                overflow: hidden;
            }

            #col3 {
                float: left;
                width: @col3Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 4;
                overflow: hidden;
            }
        }
    }
}


3

Je sais que ça fait longtemps que la question n'a pas été posée, mais j'ai trouvé une solution facile et j'ai pensé que quelqu'un pourrait l'utiliser (désolé pour le mauvais anglais). Ça y est:

CSS

.main, .sidebar {
    float: none;
    padding: 20px;
    vertical-align: top;
}
.container {
    display: table;
}
.main {
    width: 400px;
    background-color: LightSlateGrey;
    display: table-cell;
}
.sidebar {
    width: 200px;
    display: table-cell;
    background-color: Tomato;
}

HTML

<div class="container clearfix">
    <div class="sidebar">
        simple text here
    </div>
    <div class="main">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue, tortor in mattis mattis, arcu erat pharetra orci, at vestibulum lorem ante a felis. Integer sit amet est ac elit vulputate lobortis. Vestibulum in ipsum nulla. Aenean erat elit, lacinia sit amet adipiscing quis, aliquet at erat. Vivamus massa sem, cursus vel semper non, dictum vitae mi. Donec sed bibendum ante.
    </div>
</div>

Exemple simple. Notez que vous pouvez vous transformer en réactivité.


Oh, j'ai oublié: si vous voulez aligner le contenu de la barre latérale au milieu, changez simplement "vertical-align: top" en "vertical-align: middle".
Paula Fleck

2

Ma solution:

$(window).resize(function() {
   $('#div_to_occupy_the_rest').height(
        $(window).height() - $('#div_to_occupy_the_rest').offset().top
    );
});

1

Il y a une certaine contradiction dans le titre et le contenu de la question. Le titre parle d'un div parent, mais la question donne l'impression que vous voulez que deux div frères (navigation et contenu) soient de la même hauteur.

Souhaitez-vous (a) que la navigation et le contenu soient à 100% de la hauteur du principal, ou (b) que la navigation et le contenu soient à la même hauteur?

Je suppose (b) ... si tel est le cas, je ne pense pas que vous serez en mesure de le faire compte tenu de votre structure de page actuelle (du moins, pas avec du CSS pur et sans script). Vous auriez probablement besoin de faire quelque chose comme:

<main div>
    <content div>
         <navigation div></div>
    </div>
</div>

et définissez le div de contenu pour avoir une marge gauche quelle que soit la largeur du volet de navigation. De cette façon, le contenu du contenu est à droite de la navigation et vous pouvez définir la div de navigation à 100% de la hauteur du contenu.

EDIT: Je le fais complètement dans ma tête, mais vous devrez probablement également définir la marge gauche de la div de navigation sur une valeur négative ou définir sa gauche absolue sur 0 pour la repousser à l'extrême gauche. Le problème est qu'il existe de nombreuses façons de résoudre ce problème, mais tous ne seront pas compatibles avec tous les navigateurs.


1

[Se référant au moins de code de Dmity dans une autre réponse] Je suppose que c'est une sorte de "pseudo-code"?

D'après ce que je comprends, essayez d'utiliser la technique des fausses colonnes qui devrait faire l'affaire.

http://www.alistapart.com/articles/fauxcolumns/

J'espère que cela t'aides :)


4
Selon l'ordre de tri des réponses, il est difficile de dire à quoi "cela" fait référence ... Je suppose qu'il s'agit du code de Dmitry. Ainsi, cette remarque appartient à un commentaire en dessous de sa réponse! Et, pour votre information, ce n'est pas du pseudo-code, c'est du code en langage Less, une façon de définir CSS de manière procédurale.
PhiLho

1

Cette astuce fonctionne: Ajouter un élément final dans votre section de HTML avec un style de clear: both;

    <div style="clear:both;"></div>

Tout ce qui précède sera inclus dans la hauteur.


1

donner position: absolute;à l'enfant a travaillé dans mon cas


1

Vous utilisez CSS Flexbox

.flex-container {
  display: flex;
  background-color: DodgerBlue;
}

.flex-container > div {
  background-color: #f1f1f1;
  margin: 10px;
  padding: 20px;
  font-size: 30px;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>

<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div>3</div>  
</div>

<p>A Flexible Layout must have a parent element with the <em>display</em> property set to <em>flex</em>.</p>

<p>Direct child elements(s) of the flexible container automatically becomes flexible items.</p>

</body>
</html>


1

Cette réponse n'est plus idéale puisque CSS flexbox et grid ont été implémentés en CSS. Mais c'est toujours une solution de travail

Sur un écran plus petit, vous voudrez probablement conserver la hauteur automatique car les colonnes col1, col2 et col3 sont empilées les unes sur les autres.

Cependant, après un point d'arrêt de requête multimédia, vous souhaitez que les colonnes apparaissent côte à côte avec une hauteur égale pour toutes les colonnes.

1125 px n'est qu'un exemple de point d'arrêt de largeur de fenêtre après lequel vous souhaitez définir toutes les colonnes à la même hauteur.

<div class="wraper">
    <div class="col1">Lorem ipsum dolor sit amet.</div>
    <div class="col2">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eos laudantium, possimus sed, debitis amet in, explicabo dolor similique eligendi officia numquam eaque quae illo magnam distinctio odio, esse vero aspernatur.</div>
    <div class="col3">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorem, odio qui praesentium.</div>
</div>

Vous pouvez, bien sûr, définir plus de points d'arrêt si vous en avez besoin.

<script>
    $(document).ready(function(){
        $(window).on('load resize', function() {
            let vraperH = $('.wraper').height();
            if (window.innerWidth>= 1125) {
              $('.col1').height(vraperH);
              $('.col2').height(vraperH);
              $('.col3').height(vraperH);
            }
            if (window.innerWidth < 1125) {
              $('.col1').height('auto');
              $('.col2').height('auto');
              $('.col3').height('auto');
            }
        });
    });
</script>

1

J'ai eu le même problème, cela a fonctionné sur la base de la réponse de Hakam Fostok, j'ai créé un petit exemple, dans certains cas, cela pourrait fonctionner sans avoir à ajouter display: flex;et flex-direction: column;sur le conteneur parent

.row {
    margin-top: 20px;
}

.col {
    box-sizing: border-box;
    border: solid 1px #6c757d;
    padding: 10px;
}

.card {
    background-color: #a0a0a0;
    height: 100%;
}

JSFiddle


0

Comme indiqué précédemment, la flexbox est la plus simple. par exemple.

#main{ display: flex; align-items:center;}

cela alignera tous les éléments enfants au centre de l'élément parent.


3
cela ne répond pas à la question, ils veulent une hauteur égale, ne centrant pas le contenu
Ryan M


0

Voici une démo à l'ancienne basée sur le position: absoluteconteneur de contenu et le position: relativeconteneur parent.

Quant à la manière moderne de le faire - les boîtes flexibles sont les meilleures.


-3

La façon la plus simple de le faire est de le simuler. A List Apart a largement couvert cela au fil des ans, comme dans cet article de Dan Cederholm de 2004 .

Voici comment je le fais habituellement:

<div id="container" class="clearfix" style="margin:0 auto;width:950px;background:white url(SOME_REPEATING_PATTERN.png) scroll repeat-y center top;">
    <div id="navigation" style="float:left;width:190px;padding-right:10px;">
        <!-- Navigation -->
    </div>
    <div id="content" style="float:left;width:750px;">
        <!-- Content -->
    </div>
</div>

Vous pouvez facilement ajouter un en-tête à cette conception en enveloppant #container dans un autre div, en incorporant le div d'en-tête en tant que frère du conteneur # et en déplaçant les styles de marge et de largeur dans le conteneur parent. De plus, le CSS doit être déplacé dans un fichier séparé et non maintenu en ligne, etc. etc. Enfin, la classe clearfix peut être trouvée sur positioniseverything .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.