Cela me rend fou depuis quelques jours maintenant, mais en réalité c'est un problème que j'ai énormément abordé ces dernières années: avec HTML/CSS, comment puis-je créer un élément de largeur et/ou hauteur qui est 100% de son élément parent et a toujours un remplissage ou des marges appropriés?
Par "correct", je veux dire que si mon élément parent est 200px
tall et que je spécifie height = 100%
avec padding = 5px
, je suppose que je devrais obtenir un élément 190px
high avec border = 5px
de tous les côtés, bien centré dans l'élément parent.
Maintenant, je sais que ce n'est pas comme cela 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 une façon de produire cet effet de manière fiable pour un parent de taille arbitraire. Est-ce que quelqu'un connaît un moyen d'accomplir cette tâche (apparemment simple)?
Oh, et pour mémoire, la compatibilité de IE ne m'intéresse pas tellement, donc cela devrait (espérons-le) rendre les choses un peu plus faciles.
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 zone 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.
J'ai appris à faire ce genre de choses en lisant " Modèles de conception HTML et CSS ". Le display:block
est la valeur d'affichage par défaut pour la div
, mais j'aime bien le rendre explicite. Le conteneur doit être du bon type; L'attribut position
est fixed
, relative
ou 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 Nooshu's commentaire
Il existe une propriété new dans CSS3 que vous pouvez utiliser pour modifier la manière dont le modèle de boîte calcule la largeur/hauteur.
En définissant cette propriété avec la valeur "border-box", il ne sera pas nécessaire d'étirer l'élément que vous appliquez lorsque vous ajoutez un remplissage ou une bordure. Si vous définissez quelque chose avec une largeur de 100px et un remplissage de 10px, la largeur sera toujours de 100px.
box-sizing: border-box;
Voir ici pour le support du navigateur . Cela ne fonctionne pas pour IE7 et les versions antérieures, cependant, je pense que IE7.js de Dean Edward ajoute la prise en charge. Prendre plaisir :)
La solution est de ne PAS utiliser la hauteur et la largeur du tout! Fixez la boîte intérieure en utilisant le haut, la gauche, la droite, le 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>
Le meilleur moyen est d'utiliser la propriété calc (). Donc, votre cas ressemblerait à ceci:
#myDiv {
width: calc(100% - 5px);
height: calc(100% - 5px);
padding: 5px;
}
Simple, propre, pas de solutions de contournement. Assurez-vous simplement de ne pas oublier l'espace entre les valeurs et l'opérateur (par exemple (100% -5 px) qui rompra la syntaxe. Enjoy!
Selon la spécification w3c, la hauteur fait référence à la hauteur de la zone visible, par ex. sur un moniteur de résolution 1280x1024 pixels, hauteur 100% = 1024 pixels.
min-height fait référence à la hauteur totale de la page, contenu compris, donc sur une page dont le contenu est supérieur à 1024px min-height: 100% s’étendra pour inclure tout le contenu.
L'autre problème est alors que le remplissage et la bordure sont ajoutés à la hauteur et à la largeur dans la plupart des navigateurs modernes, à l'exception de ie6 (ie6 est en réalité 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 100% + 5 pixels + 5 pixels pour la hauteur. Pour contourner ce problème, vous avez besoin d'un conteneur.
<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>
1. Hauteur complète avec padding
body {
margin: 0;
}
.container {
min-height: 100vh;
padding: 50px;
box-sizing: border-box;
background: silver;
}
<div class="container">Hello world.</div>
2. Hauteur complète avec margin
body {
margin: 0;
}
.container {
min-height: calc(100vh - 100px);
margin: 50px;
background: silver;
}
<div class="container">Hello world.</div>
3. Hauteur complète 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>
C’est l’une des idioties les plus flagrantes de CSS - je n’ai pas encore compris le raisonnement (si quelqu'un sait, expliquez-le, svp).
100% signifie 100% de la hauteur du conteneur - à laquelle sont ajoutées les marges, les bordures et les rembourrages. Il est donc impossible d'obtenir un conteneur qui remplit son parent et qui possède une marge, une bordure ou un remplissage.
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 par rapport à la longueur du conteneur, c’est-à-dire sa largeur, ce qui le rend encore plus inutile en hauteur.
De nos jours, les unités de viewport vh et vw sont plus utiles, mais ne sont pas particulièrement utiles pour les conteneurs de niveau supérieur.
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 un remplissage sans le développer. L'enfant a 100% de la hauteur et de la largeur moins les rembourrages.
Une autre option consisterait à utiliser des propriétés de taille de boîte. Le seul problème avec les deux serait qu'ils ne fonctionnent pas dans IE7.
Une autre solution: vous pouvez utiliser des unités de pourcentage pour les marges ainsi que pour les tailles. Par exemple:
.fullWidthPlusMargin {
width: 98%;
margin: 1%;
}
Le principal problème ici est que les marges vont augmenter/diminuer légèrement avec la taille de l'élément parent. Vraisemblablement, la fonctionnalité que vous préférez est que les marges restent constantes et que l’élément enfant grossisse/diminue pour répondre aux changements d’espacement. Donc, en fonction de la précision de votre écran, cela pourrait poser problème. (Je préférerais aussi une marge plus faible, comme 0,3%).
L'exemple de Frank m'a un peu dérouté - cela n'a pas fonctionné dans mon cas car 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 en a parlé mais je l'ai oublié, et ce n'était pas dans son exemple).
Voici un exemple où l'enfant - un remplissage et une bordure - utilise le positionnement absolu pour remplir le parent à 100%. Le parent utilise le 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 "more-content" 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 utile link pour apprendre rapidement le positionnement CSS
Nous sommes en 2018, la nouvelle merde chaude devrait être mentionnée ici, car la question ne cesse de surgir sur Google.
Une solution avec flexbox (travaillant 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>
(Le CSS-reset n'est pas nécessairement important pour le problème actuel.)
La partie importante est flex: 1
(en combinaison avec display: flex
chez le parent). Curieusement, l'explication la plus plausible que je connaisse du fonctionnement de la propriété Flex provient d'une documentation réactive, donc je me réfère quand même .
Une autre solution - je voulais juste une simple bordure autour du bord de ma page et une hauteur de 100% lorsque le contenu était plus petit que cela.
Border-box ne fonctionnait pas et le positionnement fixe semblait inacceptable 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;
}