CSS 100% hauteur avec rembourrage / marge

813

Avec HTML / CSS, comment puis-je créer un élément dont la largeur et / ou la hauteur correspond à 100% de son élément parent et qui a toujours un remplissage ou des marges appropriés?

Par «bon», je veux dire que si mon élément parent est 200pxgrand et que je précise height = 100%avec, padding = 5pxje m'attendrais à ce que j'obtienne un 190pxélément haut avec border = 5pxde tous les côtés, bien centré dans l'élément parent.

Maintenant, je sais que ce n'est pas ainsi que le modèle de boîte standard spécifie que cela devrait fonctionner (bien que j'aimerais savoir pourquoi, exactement ...), donc la réponse évidente ne fonctionne pas:

#myDiv {
    width: 100%
    height: 100%;
    padding: 5px;
}

Mais il me semble qu'il doit y avoir QUELQUE manière de produire de manière fiable cet effet pour un parent de taille arbitraire. Quelqu'un connaît-il un moyen d'accomplir cette tâche (apparemment simple)?

Oh, et pour mémoire, je ne suis pas très intéressé par la compatibilité IE, ce qui devrait (espérons-le) faciliter les choses un peu.

EDIT: Puisqu'un exemple a été demandé, voici le plus simple auquel je puisse penser:

<html style="height: 100%">
    <body style="height: 100%">
        <div style="background-color: black; height: 100%; padding: 25px"></div>
    </body>
</html>

Le défi consiste alors à faire apparaître la boîte noire avec un remplissage de 25 pixels sur tous les bords sans que la page ne devienne suffisamment grande pour nécessiter des barres de défilement.

Toji
la source
J'ai trouvé que ces deux solutions étaient les plus fiables: http://www.xs4all.nl/~peterned/examples/csslayout1.html http://themaninblue.com/experiment/footerStickAlt/ Avez-vous un code HTML spécifique qui on peut voir et jouer avec?
Nick Presta

Réponses:

755

J'ai appris à faire ce genre de choses en lisant « Modèles de conception PRO HTML et CSS ». C'est display:blockla valeur d'affichage par défaut pour le div, mais j'aime le rendre explicite. Le conteneur doit être du bon type; positionattribut est fixed, relativeou absolute.

.stretchedToMargin {
  display: block;
  position:absolute;
  height:auto;
  bottom:0;
  top:0;
  left:0;
  right:0;
  margin-top:20px;
  margin-bottom:20px;
  margin-right:80px;
  margin-left:80px;
  background-color: green;
}
<div class="stretchedToMargin">
  Hello, world
</div>

Fiddle par le commentaire de Nooshu

Frank Schwieterman
la source
42
Superbe solution, sera mise en signet celle-ci. Il suffit de l'ajouter rapidement à jsfiddle.net/Rpdr9 pour tous ceux qui souhaitent une démonstration en direct. J'espère que cela ne vous dérange pas.
Nooshu
16
Alors que @Toji ne se souciait pas de la compatibilité IE, je dois malheureusement le faire. Cette solution ne fonctionnait pas initialement sous IE6. L'ajout d' IE9.js de Dean Edwards à la page a rendu ce travail. Maintenant, je dois juste espérer et prier pour que le positionnement relatif / absolu ne visse pas avec quelque chose dans un élément enfant ...
Christopher Parker
24
-1 (bien qu'il semble que je sois une minorité ici: P). Cela suppose que la boîte peut être absolument positionnée; les gens abusent déjà de la pos: abs comme ça, ils n'ont pas besoin de ces munitions. Prenons cet exemple: un div "panels" avec plusieurs divs de classe "panel" à l'intérieur. "panels" a {overflow: hidden; height: 300px;}, et "panel" ont différents contenus / content-height, avec {border: # 000 solid 1px; flotteur: gauche; marge droite: 10px;}. Faites tous les "panneaux" à la hauteur des "panneaux" sans perdre les bordures à aucun moment. Les divs "panel" ne peuvent pas être pos: abs'd ici. La solution de @ Marco fonctionne pour ce scénario, cependant.
eternicode
8
Oh wow, je comprends. Le top:0, bottom:0"étire" essentiellement l'élément. Je ne peux le faire fonctionner avec position:absolutesi
Matt
7
Ne pourriez-vous pas simplement le faire top:20px;bottom:20px;left:20px;right:20px;au lieu d'utiliser des marges?
chowey
391

Il y a une nouvelle propriété dans CSS3 que vous pouvez utiliser pour changer la façon dont le modèle de boîte calcule la largeur / hauteur, elle s'appelle la taille de boîte.

En définissant cette propriété avec la valeur «border-box», l'élément que vous lui appliquez ne s'étire pas lorsque vous ajoutez un remplissage ou une bordure. Si vous définissez quelque chose avec une largeur de 100 pixels et un remplissage de 10 pixels, il sera toujours de 100 pixels de large.

box-sizing: border-box;

Voir ici pour le support du navigateur . Il ne fonctionne pas pour IE7 et inférieur, cependant, je crois que IE7.js de Dean Edward ajoute un support pour cela. Prendre plaisir :)

Marco Jardim
la source
45
Finalement! J'attends cette fonctionnalité exacte depuis environ 10 ans maintenant. Dommage IE7 ne le supporte pas mais je pense toujours que les gens qui utilisent encore IE ne méritent pas une belle mise en page.
cronoklee
2
Cela a fonctionné sur iPhone / Safari et le navigateur par défaut d'Android pour moi alors que la solution absolument positionnée ci-dessus ne fonctionnait pas.
Spud
18
C'est fondamentalement le même que le modèle de boîte de mode excentrique d'IE . Je trouve drôle que tout le monde déteste sur IE, mais c'est maintenant border-boxle héros de tout le monde :)
Matt Greer
14
Pour info, le préfixe du navigateur pour le dimensionnement des boîtes est désormais supprimé pour tous sauf -moz. Voir paulirish.com/2012/box-sizing-border-box-ftw et les commentaires pour une bonne discussion
aponzani
3
Oui! C'est la bonne réponse! 100% de hauteur redimensionne désormais correctement les choses par rapport à leurs parents, sans déborder. Donnerait un million de +1 si je pouvais.
Andrew Mao
65

La solution est de ne PAS utiliser du tout la hauteur et la largeur! Fixez la boîte intérieure en haut, à gauche, à droite, en bas, puis ajoutez une marge.

.box {margin:8px; position:absolute; top:0; left:0; right:0; bottom:0}
<div class="box" style="background:black">
  <div class="box" style="background:green">
    <div class="box" style="background:lightblue">
      This will show three nested boxes. Try resizing browser to see they remain nested properly.
    </div>
  </div>
</div>

amolk
la source
6
Votez parce que vous êtes techniquement correct, mais c'est aussi fondamentalement la même réponse que Frank (ce qui, je pense, est un peu plus convivial pour les navigateurs les plus bâclés.)
Toji
39

La meilleure façon est d'utiliser la propriété calc (). Votre cas ressemblerait donc à:

#myDiv {
    width: calc(100% - 5px);
    height: calc(100% - 5px);
    padding: 5px;
}

Simple, propre, aucune solution de contournement. Assurez-vous simplement de ne pas oublier l'espace entre les valeurs et l'opérateur (par exemple, (100%-5px)cela cassera la syntaxe. Profitez-en!

Brian Aderer
la source
6
Belle solution. N'oubliez pas de vérifier la prise en charge du navigateur: puis-je utiliser calc ()
Brett Postin
5
Cela ne vous donnerait-il pas réellement 100% de largeur et de hauteur pour chaque rembourrage PLUS 5px, car le rembourrage rendrait effectivement l'élément 10px plus large et plus grand, respectivement?
Enfin une bonne solution, et pas comme les autres là-bas, vous mettez le haut, la droite, le bas et la gauche à 0, cela ne fonctionnera qu'avec la position: absolue;
Gil Epshtain
Je pense que le correct est: #myDiv {width: calc (100% - 10px); hauteur: calc (100% - 10px); rembourrage: 5px; } 5 de gauche et 5 de droite = 10, 5 de haut et 5 de bas = 10
Chris P
21

Selon la hauteur de spécification w3c se réfère à la hauteur de la zone visible par exemple sur un moniteur de résolution 1280x1024 pixels hauteur 100% = 1024 pixels.

min-height fait référence à la hauteur totale de la page, y compris le contenu, donc sur une page dont le contenu est supérieur à 1024px min-height: 100% s'étirera pour inclure tout le contenu.

L'autre problème est alors que le rembourrage et la bordure sont ajoutés à la hauteur et à la largeur dans la plupart des navigateurs modernes sauf ie6 (ie6 est en fait assez logique mais n'est pas conforme à la spécification). C'est ce qu'on appelle le modèle de boîte. Donc, si vous spécifiez

min-height: 100%;
padding: 5px; 

Cela vous donnera en fait 100% + 5px + 5px pour la hauteur. Pour contourner cela, vous avez besoin d'un conteneur d'emballage.

<style>
    .FullHeight { 
       height: auto !important; /* ie 6 will ignore this */
       height: 100%;            /* ie 6 will use this instead of min-height */
       min-height: 100%;        /* ie 6 will ignore this */
    }

    .Padded {
       padding: 5px;
    }
</style>

<div class="FullHeight">
   <div class="Padded">
      Hello i am padded.
   </div
</div>
Alex
la source
4
@Alex: Mais qu'est-ce qui fait que le div intérieur (le rembourré) 100% de la hauteur du div extérieur. Mon expérience a été que vous obtenez juste un petit div court à l'intérieur d'un plus grand div pleine hauteur.
Lawrence Dol
8

1. Pleine hauteur avec padding

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  padding: 50px;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

2. Pleine hauteur avec margin

body {
  margin: 0;
}
.container {
  min-height: calc(100vh - 100px);
  margin: 50px;
  background: silver;
}
<div class="container">Hello world.</div>

3. Hauteur totale avec border

body {
  margin: 0;
}
.container {
  min-height: 100vh;
  border: 50px solid pink;
  box-sizing: border-box;
  background: silver;
}
<div class="container">Hello world.</div>

Autocollants
la source
7

C'est l'une des idioties pure et simple de CSS - je n'ai pas encore compris le raisonnement (si quelqu'un le sait, veuillez expliquer).

100% signifie 100% de la hauteur du conteneur - auquel sont ajoutées les marges, bordures et rembourrages. Il est donc effectivement impossible d'obtenir un conteneur qui remplit son parent et qui a une marge, une bordure ou un rembourrage.

Notez également que le réglage de la hauteur est notoirement incohérent entre les navigateurs.


Une autre chose que j'ai apprise depuis que j'ai posté ceci est que le pourcentage est relatif à la longueur du conteneur , c'est-à-dire sa largeur, ce qui rend un pourcentage encore plus inutile pour la hauteur.

De nos jours, les unités de fenêtre vh et vw sont plus utiles, mais toujours pas particulièrement utiles pour autre chose que les conteneurs de niveau supérieur.

Lawrence Dol
la source
Il n'y a pas de raisonnement, juste ce qui s'est passé lorsque les navigateurs ont commencé à converger vers un comportement cohérent. Consultez le livre mentionné dans ma réponse.
Frank Schwieterman
A voté pour l'utilisation du bon terme. Tex et tout gestionnaire de mise en page que j'ai vu ont raison, juste CSS doit être spécial.
maaartinus
5

Une autre solution consiste à utiliser display: table qui a un comportement de modèle de boîte différent.

Vous pouvez définir une hauteur et une largeur pour le parent et ajouter du rembourrage sans l'agrandir. L'enfant a 100% de hauteur et de largeur moins les rembourrages.

JSBIN

Une autre option serait d'utiliser une propriété de dimensionnement de boîte. Le seul problème avec les deux serait qu'ils ne fonctionnent pas dans IE7.

user1721135
la source
4

Une autre solution: vous pouvez utiliser des unités de pourcentage pour les marges ainsi que les tailles. Par exemple:

.fullWidthPlusMargin {
    width: 98%;
    margin: 1%;
}

Le principal problème ici est que les marges augmenteront / diminueront légèrement avec la taille de l'élément parent. Vraisemblablement, la fonctionnalité que vous préféreriez est que les marges restent constantes et que l'élément enfant s'agrandisse / se rétrécisse pour combler les changements d'espacement. Ainsi, en fonction de l'étroitesse de votre écran, cela pourrait être problématique. (Je choisirais également une marge plus petite, comme 0,3%).

ktbiz
la source
3

Une solution avec flexbox (fonctionnant sur IE11): ( ou vue sur jsfiddle )

<html>
  <style>
    html, body {
      height: 100%; /* fix for IE11, not needed for chrome/ff */
      margin: 0; /* CSS-reset for chrome */
    }
  </style>
  <body style="display: flex;">
    <div style="background-color: black; flex: 1; margin: 25px;"></div>
  </body>
</html>

(La réinitialisation CSS n'est pas nécessairement importante pour le problème réel.)

La partie importante est flex: 1(en combinaison avec display: flexchez le parent). Curieusement, l'explication la plus plausible que je connaisse sur le fonctionnement de la propriété Flex provient d'une documentation native native, donc j'y fais référence quand même :

(...) flex: 1, qui indique à un composant de remplir tout l'espace disponible, partagé également entre les autres composants avec le même parent

Putzi San
la source
2

L'exemple de Frank m'a un peu dérouté - cela n'a pas fonctionné dans mon cas parce que je ne comprenais pas encore assez bien le positionnement. Il est important de noter que l'élément conteneur parent doit avoir une position non statique (il l'a mentionné mais je l'ai ignoré, et ce n'était pas dans son exemple).

Voici un exemple où l'enfant - avec un rembourrage et une bordure - utilise un positionnement absolu pour remplir le parent à 100%. Le parent utilise un positionnement relatif afin de fournir un point de référence pour la position de l'enfant tout en restant dans le flux normal - l'élément suivant "plus de contenu" n'est pas affecté:

#box {
    position: relative;
    height: 300px;
    width: 600px;
}

#box p {
    position: absolute;
    border-style: dashed;
    padding: 1em;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
<div id="box">
  <p>100% height and width!</p>
</div>
<div id="more-content">
</div>

Un lien utile pour apprendre rapidement le positionnement CSS

Peter Tseng
la source
0

Bordure autour de div, plutôt que marge du corps de la page

Une autre solution - je voulais juste une simple bordure autour du bord de ma page, et je voulais 100% de hauteur lorsque le contenu était plus petit que cela.

Border-box ne fonctionnait pas, et le positionnement fixe semblait incorrect pour un besoin aussi simple.

J'ai fini par ajouter une bordure à mon conteneur, au lieu de compter sur la marge du corps de la page - cela ressemble à ceci:

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

.container {
    width: 100%;
    min-height: 100%;
    border: 8px solid #564333;
}
Kris Randall
la source
0

Il s'agit du comportement par défaut de display: blockLa façon la plus rapide de le corriger en 2020 est de définir l' display: 'flex'élément parent et le remplissage, par exemple 20 pixels, puis tous ses enfants auront 100% de hauteur par rapport à sa hauteur.

Freestyle09
la source
0

Ajouter -webkit et -moz serait plus approprié

-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
user3113626
la source
-2
  <style type="text/css">
.stretchedToMargin {
    position:absolute;
    width:100%;
    height:100%;

}
</style>
Mujassir Nasir
la source