Utilisation de la marge: auto pour aligner verticalement un div


113

Donc, je sais que nous pouvons centrer une div horizontalement si nous utilisons margin:0 auto;. Devrait margin:auto auto;fonctionner comme je pense que cela devrait fonctionner? Le centrer verticalement également?

Pourquoi ne vertical-align:middle;fonctionne pas non plus?

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

JSFiddle


1
Suggère vivement de lire et de mettre en œuvre la réponse de @ zpr ci-dessous concernant Flexbox. Il est assez bien pris en charge à partir d'aujourd'hui et votre css sera beaucoup, beaucoup plus propre.
Govind Rai

if ((new Date ()). getFullYear ()> 2017) useFlexBox = true;
Brandito

Réponses:


173

Mise à jour août 2020

Bien que ce qui suit vaut toujours la peine d'être lu pour les informations utiles, nous avons Flexbox depuis un certain temps maintenant, alors utilisez-le simplement, conformément à cette réponse .


Vous ne pouvez pas utiliser:

vertical-align:middlecar il ne s'applique pas aux éléments de niveau bloc

margin-top:autoet margin-bottom:autoparce que leurs valeurs utilisées seraient égales à zéro

margin-top:-50%car les valeurs de marge basées sur un pourcentage sont calculées par rapport à la largeur du bloc conteneur

En fait, la nature du flux de documents et les algorithmes de calcul de la hauteur des éléments rendent impossible l'utilisation des marges pour centrer un élément verticalement à l'intérieur de son parent. Chaque fois que la valeur d'une marge verticale est modifiée, cela déclenchera un recalcul de la hauteur de l'élément parent (re-flux), qui à son tour déclencherait un recentrage de l'élément d'origine ... en faisant une boucle infinie.

Vous pouvez utiliser:

Quelques solutions de contournement comme celle-ci qui fonctionnent pour votre scénario; les trois éléments doivent être imbriqués comme ceci:

.container {
    display: table;
    height: 100%;
    position: absolute;
    overflow: hidden;
    width: 100%;
}
.helper {
    #position: absolute;
    #top: 50%;
    display: table-cell;
    vertical-align: middle;
}
.content {
    #position: relative;
    #top: -50%;
    margin: 0 auto;
    width: 200px;
    border: 1px solid orange;
}
<div class="container">
    <div class="helper">
        <div class="content">
            <p>stuff</p>
        </div>
    </div>
</div

JSFiddle fonctionne correctement selon Browsershot.


10
#est un hack pour avoir la règle préfixée avec elle uniquement interprétée par IE7 et moins. Vous pouvez préférer inclure ces règles plutôt que dans une feuille de style spécifique à IE en utilisant des commentaires conditionnels , etc.
ov

2
+1 pour les raisons pour lesquelles c'est le cas, le calcul du pourcentage de marge basé sur la largeur a été très révélateur.
ricosrealm

2
Je doute de la déclaration «boucle infinie».
Barun du

105
l'humanité est déjà allée sur la lune il y a des années et nous devons encore faire face à ces conneries. aligner verticalement les choses dans un navigateur, jesus
user151496

3
À l'âge> = IE9, position: absolute; top: 50%; transform: translateY(-50%);c'est aussi faisable et assez populaire ... (contrairement à top:50%;margin: - $halfHeightce que vous n'avez pas besoin de connaître la taille à l'avance ...)
Frank Nocke

112

Depuis que cette question a été posée en 2012 et que nous avons parcouru un long chemin avec le support du navigateur pour les flexbox, j'ai eu l'impression que cette réponse était obligatoire.

Si l'affichage de votre conteneur parent est flex, alors oui , margin: auto auto(également appelé margin: auto) fonctionnera pour le centrer à la fois horizontalement et verticalement, qu'il s'agisse d'un élément inlineou block.

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
}
#child {
    margin: auto auto;
}
<div id="parent">
    <div id="child">hello world</div>
</div>

Notez que la largeur / hauteur n'a pas à être spécifiée de manière absolue, comme dans cet exemple jfiddle qui utilise le dimensionnement par rapport à la fenêtre.

Bien que la prise en charge des boîtiers flexibles par les navigateurs soit à un niveau record au moment de la publication, de nombreux navigateurs ne la prennent toujours pas en charge ou nécessitent des préfixes de fournisseur. Consultez http://caniuse.com/flexbox pour obtenir des informations mises à jour sur la prise en charge du navigateur.

Mettre à jour

Étant donné que cette réponse a reçu un peu d'attention, je tiens également à souligner que vous n'avez pas du tout besoin de spécifier marginsi vous utilisez display: flexet souhaitez centrer tous les éléments du conteneur:

#parent {
    width: 50vw;
    height: 50vh;
    background-color: gray;
    display: flex;
    align-items: center; /* horizontal */
    justify-content: center; /* vertical */
}
<div id="parent">
    <div>hello world</div>
</div>


4
parent {affichage: flex; } enfant {marge: auto 0; } est tout simplement génial.
Arek Kostrzeba

OMG mec, tu es un homme rockstar, putain je ne peux pas te voter plus d'une fois !!!
PirateApp

C'est une bonne réponse lorsque vous pouvez également être confondu avec le problème d'ajustement du contenu. En définissant flex sur le conteneur, le div de contenu n'a pas besoin de propriétés à définir.
Eric

1
C'est de loin la solution la meilleure et la plus élégante pour travailler en 2018, merci.
SilverSurfer

Je voudrais ajouter qu'à partir de mai 2018, avec cette solution, le texte ne s'aligne pas verticalement au milieu dans IE 11.
Yefu

62

Voici la meilleure solution que j'ai trouvée: http://jsfiddle.net/yWnZ2/446/ Fonctionne dans Chrome, Firefox, Safari, IE8-11 et Edge.

Si vous avez une déclaration height( height: 1em, height: 50%, etc.) ou il est un élément sur lequel le navigateur connaît la hauteur ( img, svgou canvaspar exemple), tout ce que vous avez besoin pour le centrage vertical est la suivante:

.message {
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
    margin: auto;
}

Vous voudrez généralement spécifier un widthou max-widthdeux, le contenu ne s'étend pas sur toute la longueur de l'écran / du conteneur.

Si vous l'utilisez pour un modal que vous souhaitez toujours centré dans la fenêtre chevauchant un autre contenu, utilisez position: fixed;pour les deux éléments au lieu de position: absolute. http://jsfiddle.net/yWnZ2/445/

Voici un résumé plus complet: http://codepen.io/shshaw/pen/gEiDt


3
Cela ne le centre pas nécessairement dans son élément parent. Bon hack si vous le voulez juste au centre de la page.
Joel Mellon

2
Ajoutez simplement position: relativeau parent, et l'élément sera centré dans le parent. J'ai rédigé un article beaucoup plus large sur Smashing Magazine sur la technique si vous souhaitez en savoir plus: coding.smashingmagazine.com/2013/08/09/…
shshaw

Parfois, l'absolu est basé sur un parent ou deux (contre le corps) et le parent peut être un grand ou un arrière-grand-parent (contre le parent). Peut-être que ceux qui savent quand ou pourquoi cela se produit pourraient mieux contrôler cette technique - je n'ai jamais vraiment examiné ces problèmes, mais je sais que passer de l'absolu au relatif n'est pas en soi une solution pour que cela fonctionne. J'ai lu un peu de votre article et il semble que l'absolu et le relatif remontent au premier ancêtre absolu ou relatif, est-ce exact?
Joel Mellon

Je suis un peu lent. Je viens de relire votre commentaire ci-dessus. Je n'ai pas remarqué que vous aviez dit de l'ajouter au parent- je l'ai compris. Merci beaucoup!
Joel Mellon

1
@commonpike Le seul problème avec IE8 / 9 est si vous utilisez display: tablepour un contenu à hauteur variable. Sinon, cette méthode devrait fonctionner comme prévu. Lisez l' ensemble pour plus de détails. Vous devriez également pouvoir tester la vue complète dans IE8 / 9 pour voir s'il y a des problèmes.
shshaw

22

Edit: c'est 2020, j'utiliserais plutôt une boîte flexible.

Réponse originale:

HTML

<body>
  <div class="centered">
  </div>
</body>

CSS

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

ne fonctionnerait pas pour IE 8 et les versions antérieures de ie. Puisque la propriété de transformation est prise en charge (avec le préfixe -ms-) à partir de la version 9.0 et plus. (c'est-à-dire que 10 n'ont plus besoin de préfixe).
DevWL

5
Certes, je m'en fiche de IE8
Gal Margalit

Et l'écrivain a tagué html5 pour sa question ☺
Gal Margalit

9

Je sais que la question date de 2012, mais j'ai trouvé le moyen le plus simple et je voulais partager.

HTML:

<div id="parent">
     <div id="child">Content here</div>
</div>

et CSS:

#parent{
     height: 100%;
     display: table;
}    
#child {
     display: table-cell;
     vertical-align: middle; 
}

7

Si vous connaissez la hauteur du div que vous souhaitez centrer , vous pouvez le positionner de manière absolue dans son parent, puis définir la topvaleur sur 50%. Cela mettra le haut du div enfant à 50% de son parent, c'est-à-dire trop bas. Tirez-le vers le haut en le réglant margin-topà la moitié de sa hauteur. Alors maintenant, vous avez le milieu vertical du div enfant assis au milieu vertical du parent - centré verticalement!

Exemple:

.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    background:yellow;
    width:200px;
    margin:auto auto;
    padding:10px;
    position: absolute;
    top: 50%;
    margin-top: -25px;
    height: 50px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

http://jsfiddle.net/yWnZ2/2/


1
margin-topne peut être exprimée en% par rapport à la hauteur de l' élément, de sorte que vous vous retrouverez avec une dimension fixe dépendante
ov

1
C'est ... exactement ce que j'ai dit dans ma réponse? "Si vous connaissez la hauteur de la div que vous voulez centrer". Et je n'ai pas dit que OP devrait utiliser% in margin-top.
tuff

Je ne suis pas d'accord avec la solution car elle vous enferme dans une hauteur d'élément prédéfinie - mais votre commentaire a du sens. Vous voudrez peut - être refléter le fait que dans la réponse
ov

3
OK, j'ai mis en gras la partie que vous avez négligée, j'espère que c'est plus clair maintenant.
tuff le

1
@ov: Si l'élément n'a pas de hauteur fixe, vous pouvez simplement utiliser JS pour obtenir la hauteur calculée, puis définir la marge supérieure négative en conséquence. C'est toujours la meilleure méthode de centrage vertical, à mon avis.
daGUY le

3

Ces deux solutions ne nécessitent que deux éléments imbriqués.
Première - Positionnement relatif et absolu si le contenu est statique (centre manuel).

.black {
    position:relative;
    min-height:500px;
    background:rgba(0,0,0,.5);

}
.message {
    position:absolute;
    margin: 0 auto;
    width: 180px;
    top: 45%; bottom:45%;  left: 0%; right: 0%;
}

https://jsfiddle.net/GlupiJas/5mv3j171/

ou pour une conception fluide - pour le centre de contenu exact, utilisez plutôt l'exemple ci-dessous:

.message {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

https://jsfiddle.net/GlupiJas/w3jnjuv0/

Vous devez définir «hauteur min» au cas où le contenu dépasserait 50% de la hauteur de la fenêtre. Vous pouvez également manipuler cette hauteur avec une requête multimédia pour les appareils mobiles et tablettes. Mais seulement si vous jouez avec un design réactif.

Je suppose que vous pouvez aller plus loin et utiliser un simple script JavaScript / JQuery pour manipuler la hauteur minimale ou la hauteur fixe s'il y a un besoin pour une raison quelconque.

Deuxièmement - si le contenu est fluide, vous pouvez également utiliser les propriétés css de table et de cellule de tableau avec un alignement vertical et un alignement du texte centré:

/*in a wrapper*/  
display:table;   

et

/*in the element inside the wrapper*/
display:table-cell;
vertical-align: middle;
text-align: center;

Fonctionne et s'adapte parfaitement, souvent utilisée comme solution de conception Web réactive avec des mises en page de grille et des requêtes multimédias qui manipulent la largeur de l'objet.

.black {
    display:table;
    height:500px;
    width:100%;
    background:rgba(0,0,0,.5);

}
.message {
    display:table-cell;
    vertical-align: middle;
    text-align: center;
}

https://jsfiddle.net/GlupiJas/4daf2v36/

Je préfère une solution de table pour le centrage exact du contenu, mais dans certains cas, le positionnement absolu relatif fera mieux, surtout si nous ne voulons pas conserver la proportion exacte d'alignement du contenu.


2

.black {
    display:flex;
    flex-direction: column;
    height: 200px;
    background:grey
}
.message {
    background:yellow;
    width:200px;
    padding:10px;
    margin: auto auto;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>


Pourriez-vous s'il vous plaît partager avec nous, en quoi consiste cette solution? De plus, je vois votre "message contextuel" en bas non centré
Alex

J'ai raté quelque chose, mais maintenant c'est raffiné pour garder le div au milieu verticalement. vous pouvez vérifier maintenant.
Seetpal singh le

0

Il n'y a pas un moyen facile de centrer la div verticalement qui ferait l'affaire dans toutes les situations.

Cependant, il existe de nombreuses façons de le faire en fonction de la situation.

En voici quelques-uns:

  • Définissez le remplissage supérieur et inférieur de l'élément parent, par exemple, le remplissage: 20px 0px 20px 0px
  • Utiliser un tableau, la cellule du tableau centre son contenu verticalement
  • Définissez la position relative de l'élément parent et les div que vous souhaitez centrer verticalement sur absolus et définissez-le comme top: 50px; bas: 50px; par exemple

Vous pouvez également rechercher sur Google le "centrage vertical css"


0

hauteur variable, marge haut et bas auto

.black {background:rgba(0,0,0,.5);
width: 300px;
height: 100px;
display: -webkit-flex; /* Safari */
display: flex;}
.message{
background:tomato;
margin:auto;
padding:5%;
width:auto;
}
<div class="black">
<div class="message">
    This is a popup message.
</div>

hauteur variable, marge haut et bas auto


0

Utilisation de Flexbox:

HTML:

<div class="container">
  <img src="http://lorempixel.com/400/200" />
</div>

CSS:

.container {
  height: 500px;
  display: flex;
  justify-content: center; /* horizontal center */
  align-items: center;     /* vertical center */
}

Voir résultat


0
.black {
    position:absolute;
    top:0;
    bottom:0;
    left:0;
    right:0;
    background:rgba(0,0,0,.5);
}
.message {
    position: absolute;
    top:50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background:yellow;
    width:200px;
    padding:10px;
}

 - 


----------


<div class="black">
<div class="message">
    This is a popup message.
</div>
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.