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?

TylerH
la source
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.

cletus
la source
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>

Aiphee
la source
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.

Travis
la source
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.

Paul Harvey
la source
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 .

David dit de réintégrer Monica
la source
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;
}
Roman Kuntyi
la source
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();
});
flavius
la source
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%;
Tony C
la source
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 .

Sergiu
la source
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.

Lajos Meszaros
la source
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.

Hakan Fıstık
la source
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;
            }
        }
    }
}
Dmitry Efimenko
la source
4

Ajouter display: gridau parent

Dziamid
la source
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é.

Paula Fleck
la source
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
    );
});
Rafael Ruiz Muñoz
la source
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.

Paul Abbott
la source
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 :)

jluna
la source
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.

user945389
la source
1

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

neoDev
la source
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>

Ini
la source
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>
DevWL
la source
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

Builo
la source
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.

Chandan Purohit
la source
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.

WebBrother
la source
-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 .

Aaron Brethorst
la source