web-dev-qa-db-fra.com

Pourquoi la marge ne serait-elle pas contenue par l'élément parent?

Lorsqu'un élément avec une marge est contenu dans un autre élément, le parent n'encapsule/contient pas systématiquement cette marge.

Beaucoup de choses amèneront le parent à contenir la marge de l'enfant:

  • border: solid;
  • position: absolute;
  • display: inline-block;
  • overflow: auto;

(Et c'est juste à partir d'un petit test, sans doute il y en a plus.)

Je suppose que cela a à voir avec l'effondrement des marges, mais:

  1. La page de spécifications du W3C n'a pas de description d'un tel comportement.
  2. Il n'y a pas de marges qui se chevauchent ici.
  3. Le comportement de tous les navigateurs semble cohérent sur ce problème.
  4. Le comportement est affecté par des déclencheurs qui ne sont pas liés aux marges.

Quelle est la logique par laquelle un élément par défaut à overflow: auto doit contenir un matériau différent de celui où le débordement est réglé sur auto?

Pourquoi tout sauf le comportement par défaut d'un div normal devrait-il supposer que la marge est contenue par le parent - et pourquoi le défaut normal ne devrait-il pas inclure la marge?


EDIT: La réponse finale est que le W3C spécifie vraiment ce comportement, mais que:

  • Les spécifications n'ont pas vraiment de sens.
  • Le mix des spécifications, sans mot d'explication :
    • 'marges libres' (les marges qui toucheraient le haut ou le bas de leur parent ne sont pas contenues par le parent) et
    • "marges réduites" (les marges adjacentes peuvent se chevaucher).

Démo:

body {
  margin: 0;
}

div.block {
  background-color: skyblue;
}
div.inline-block {
  display: inline-block;
  background-color: lawngreen;
}
div.position-absolute {
  background-color: rgba(255,255,0,.7);
  position: absolute;
  bottom: 0;
  right: 0;
}
div.overflow-auto {
  background-color: hotpink;
  overflow: auto;
}
div.border {
  background-color: aquamarine;
  border: solid;
}

h2 {
  margin: 80px;
  width: 250px;
  border: solid;
}
<div class="block">
  <h2>Is the margin contained (block)?</h2>
</div>
<div class="inline-block">
  <h2>Is the margin contained (inline-block)?</h2>
</div>
<div class="position-absolute">
  <h2>Is the margin contained (position-absolute)?</h2>
</div>
<div class="overflow-auto">
  <h2>Is the margin contained (overflow-auto)?</h2>
</div>
<div class="border">
  <h2>Is the margin contained (border)?</h2>
</div>
52
SamGoody

Voici comment fonctionne CSS selon W3C :

Dans cette spécification, l'expression marges réduites signifie que les marges adjacentes (pas de contenu non vide, de remplissage ou de zones de bordure ou de séparation les séparent) de deux ou plusieurs boîtes (qui peuvent être côte à côte ou imbriquées) se combinent pour former un marge unique.

Plus spécifique à votre cas de div supérieur:

Si les marges supérieure et inférieure d'une boîte sont adjacentes, il est possible que les marges se réduisent à travers elle. Dans ce cas, la position de l'élément dépend de sa relation avec les autres éléments dont les marges sont réduites.

  • Si les marges de l'élément sont réduites avec la marge supérieure de son parent, le bord supérieur de la bordure de la zone est défini comme étant identique à celui du parent.
  • Sinon, soit le parent de l'élément ne participe pas à l'effondrement de la marge, soit seule la marge inférieure du parent est impliquée. La position de la bordure supérieure de l'élément Edge est la même que si elle avait été si l'élément avait une bordure inférieure non nulle.

La meilleure chose que je puisse faire est de vous indiquer "Collapsing Margins" sur sitepoint (par Tommy Olsson et Paul O'Brien). Ils font une explication très très détaillée avec des exemples vous montrant exactement les comportements que vous avez démontrés dans l'exemple de code de question.

27
Nick Craver