web-dev-qa-db-fra.com

Pourquoi "margin: auto" ne centre-t-il pas un élément verticalement?

Comme vous pouvez le voir dans la démo ci-dessous, margin: auto; centre le bleu div horizontalement, mais pas verticalement. Pourquoi pas?

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto;
}
<div class="box">
  <div class="center"></div>
</div>

Ma question ne demande pas de solutions de contournement.

46
Stickers

Comme mentionné, ce comportement est spécifié dans section 10.6.2 de CSS2.1, et est resté inchangé par rapport à CSS2 .

Les boîtes à blocs sont empilées verticalement de haut en bas dans un flux normal. De plus, les marges verticales peuvent s'effondrer , et ne le faites que dans certaines circonstances (dans votre démo, la bordure de l'élément parent empêchera les marges de l'élément enfant de s'effondrer avec les siennes). Si vous ne disposez que d'une seule case de bloc et que la hauteur du bloc contenant est auto, ses marges supérieure et inférieure seront de toute façon nulles. Mais si vous avez plus d'une boîte de bloc dans le même flux, ou même des boîtes hors flux affectant la disposition des boîtes en flux (dans le cas de clairance par exemple), comment feriez-vous attendez-vous à ce que les marges automatiques se résolvent pour ces boîtes d'entrée?

C'est pourquoi les marges gauche et droite automatiques sont également mises à zéro pour les éléments en ligne (y compris les lignes atomiques) et les flottants (bien que les marges horizontales ne se réduisent jamais). Les boîtes de niveau en ligne sont posées le long des boîtes de ligne , et les flotteurs obéissent trop règles de mise en page uniques .

Les boîtes absolument positionnées sont une autre histoire: puisqu'elles ne connaissent jamais d'autres boîtes dans le même contexte de positionnement qu'eux-mêmes, les marges supérieure et inférieure automatiques peuvent être calculé pour eux par rapport à leurs blocs contenant sans avoir à se soucier de toute autre boîte qui interfère jamais.

Flexbox est également une autre histoire: ce qui distingue la mise en page flexible de la mise en page par blocs, c'est que les éléments flexibles sont par définition toujours conscients des autres éléments flexibles dans le même contexte de mise en forme flexible, y compris le fait qu'il n'y en a pas. En particulier, ni les flottants ne peuvent s'immiscer dans le conteneur flex, ni les éléments flex pour les inverser (bien que vous puissiez toujours supprimer complètement un élément enfant de la disposition flex avec positionnement absol =). Les marges se comportent très différemment avec les éléments flexibles en partie à cause de cela. Voir les sections 4.2 , 9.5 et 9.6 .

36
BoltClock

Pourquoi ... parce que le W3C spec le dit.

Si "margin-top" ou "margin-bottom" sont "auto", leur valeur utilisée est 0.

Quant au "pourquoi" réel ... la requête devrait vraiment y être adressée.

30
Paulie_D

Il ne centre pas l'élément verticalement car il s'agit d'un élément de niveau bloc dans le flux normal. Ainsi, la la règle suivante s'applique :

Si margin-top, ou margin-bottom sont auto, leur valeur utilisée est 0.

Il convient également de noter que la règle ci-dessus s'applique également aux éléments suivants: (voir points 10.6.2 et 10.6. pour plus d'informations et conditions).

  • Éléments remplacés en ligne
  • Éléments remplacés au niveau du bloc dans un flux normal
  • inline-block éléments remplacés en écoulement normal
  • Éléments flottants remplacés
  • Éléments non remplacés au niveau du bloc dans le flux normal lorsque overflow calcule en visible

Cela étant dit, les éléments non positionnés et absolument remplacés qui n'ont pas les valeurs top, height et bottom de auto sont une exception à cette règle. Ce qui suit s'applique à partir de point 10.6.4 :

Si aucun des trois top, height et bottom n'est auto et si les deux margin-top et margin-bottom sont auto, résolvent l'équation sous la contrainte supplémentaire que les deux marges obtiennent des valeurs égales .

Voir l'exemple ci-dessous montrant comment un élément absolument positionné est centré verticalement à l'aide de margin: auto. Cela fonctionne car aucune des trois propriétés top, height et bottom n'a la valeur auto:

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
  position: relative;
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto;
  position: absolute;
  top: 0; right: 0;
  bottom: 0; left: 0;
}
<div class="box">
  <div class="center"></div>
</div>

De plus, il vaut probablement la peine de souligner également règle suivante :

Si l'un des margin-top ou margin-bottom est auto, résolvez l'équation pour cette valeur. Si les valeurs sont trop contraintes, ignorez la valeur de bottom et résolvez pour cette valeur.

Cela signifie que si l'élément absolument positionné a un margin-top valeur de auto et d'un margin-bottom valeur de 0 (c'est à dire., margin: auto auto 0), l'élément serait absolument positionné en bas par rapport au parent comme dans l'exemple ci-dessous:

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
  position: relative;
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto auto 0;
  position: absolute;
  top: 0; right: 0;
  bottom: 0; left: 0;
}
<div class="box">
  <div class="center"></div>
</div>
16
Josh Crozier

Pourquoi margin:auto travailler verticalement?

En fait, c'est le cas, mais pas pour chaque valeur de display.

Si display est flex, margin: auto centre verticalement et horizontalement.

De même pour display: inline-flex, display: grid et display: inline-grid.

.box {
  border: 1px solid red;
  width: 100px;
  height: 100px;
  display: flex; /* new */
}
.center {
  background: blue;
  width: 50px;
  height: 50px;
  margin: auto;
}
<div class="box">
  <div class="center"></div>
</div>
14
Michael_B

C'est en raison de la possibilité réelle de connaître la hauteur réelle de l'élément dans lequel vous souhaitez centrer verticalement. Pour comprendre cela, pensez d'abord au fonctionnement du centrage horizontal automatique. Vous avez un div auquel vous lui avez donné une largeur (fixe ou pourcentage). La largeur peut être calculée dans une certaine mesure. Si c'est une largeur fixe, tant mieux. S'il est flexible ou réactif (pourcentage) au moins, vous avez une plage que la largeur couvrira avant d'atteindre le prochain point d'arrêt. Vous prenez cette largeur, moins ce qu'elle est à l'intérieur et vous divisez le reste des deux côtés.

Maintenant, avec ces informations, comment le navigateur pourrait-il calculer la quantité infinie de variations dans lesquelles votre div grandira verticalement? Gardez à l'esprit la taille de l'élément, l'habillage du texte, les rembourrages et la réactivité modifieront également la largeur et forceront le texte à envelopper davantage, et ainsi de suite.

Est-ce une tâche impossible? Pas vraiment, CSS a-t-il consacré du temps et des efforts à couvrir cela? Ne vaut pas leur temps, je suppose.

Et c'est essentiellement la réponse que je dis à mes élèves.

Mais ... ne vous inquiétez pas! Bootstrap v4 alpha a compris centrage vertical !

[~ # ~] modifier [~ # ~]

Désolé d'éditer cela tard mais j'ai pensé que vous voudrez peut-être considérer ces solutions pour centrer verticalement et c'est assez simple en utilisant la fonction calc

<div class="foo"></div>

.foo {
  background-color: red;
  height: 6em;
  left: calc(50% - 3em);
  position: absolute;
  top: calc(50% - 3em);
  width: 6em;
}

Voir [~ # ~] ici [~ # ~]

3
LOTUSMS