Comment centrer verticalement le contenu avec une hauteur variable dans un div?

158

Quelle est la meilleure façon de centrer verticalement le contenu d'un div lorsque la hauteur du contenu est variable. Dans mon cas particulier, la hauteur du conteneur div est fixe, mais ce serait formidable s'il y avait une solution qui fonctionnerait dans les cas où le conteneur a également une hauteur variable. Aussi, j'aimerais une solution sans ou très peu d'utilisation de hacks CSS et / ou de balisage non sémantique.

texte alternatif

Jességavin
la source
la méthode dans cet article s'effondre dans Safari (4.0.5): S
7
@ ripper234 Pas exactement, car cette question concerne la hauteur variable div
Rauli Rajande
9
Aussi, cette question a été posée en premier.
Gui Imamura

Réponses:

147

Il suffit d'ajouter

position: relative;
top: 50%;
transform: translateY(-50%);

à la div interne.

Ce qu'il fait, c'est déplacer la bordure supérieure du div interne à la moitié de la hauteur du div externe ( top: 50%;), puis le div interne vers le haut de la moitié de sa hauteur ( transform: translateY(-50%)). Cela fonctionnera avec position: absoluteou relative.

Gardez à l'esprit cela transformet translateayez des préfixes de fournisseur qui ne sont pas inclus pour plus de simplicité.

Codepen: http://codepen.io/anon/pen/ZYprdb

NoirCetha
la source
6
Je me suis simplement demandé pourquoi cela fonctionne sur Chrome et Firefox, mais pas sur Safari. Ensuite, j'ai remarqué que la plupart transformdes trucs connexes sont -webkit-préfixés et maintenant cela fonctionne. Alors juste pour rappel: n'oubliez pas d'ajouter le -webkit-préfixe aussi.
miho
5
Utilisez un outil tel que github.com/postcss/autoprefixer pour gérer les préfixes à votre place.
Jamie Chong
6
Cette réponse devrait être en haut.
Jose Faeti
3
Cela devrait avoir beaucoup plus de votes positifs! Au fait, cela fonctionne aussi avec position: absolute, n'est-ce pas?
caw
4
Cette méthode a un effet secondaire malheureux dans Chrome - si votre wrapper a un nombre impair de pixels, translatele rendu sera flou en essayant de gérer une hauteur de 0,5 px sur tout.
Keith
157

Cela semble être la meilleure solution que j'ai trouvée à ce problème, tant que votre navigateur prend en charge le ::beforepseudo élément: CSS-Tricks: Centering in the Unknown .

Il ne nécessite aucun balisage supplémentaire et semble fonctionner extrêmement bien. Je n'ai pas pu utiliser la display: tableméthode car les tableéléments n'obéissent pas à la max-heightpropriété.

.block {
  height: 300px;
  text-align: center;
  background: #c0c0c0;
  border: #a0a0a0 solid 1px;
  margin: 20px;
}

.block::before {
  content: '';
  display: inline-block;
  height: 100%; 
  vertical-align: middle;
  margin-right: -0.25em; /* Adjusts for spacing */

  /* For visualization 
  background: #808080; width: 5px;
  */
}

.centered {
  display: inline-block;
  vertical-align: middle;
  width: 300px;
  padding: 10px 15px;
  border: #a0a0a0 solid 1px;
  background: #f5f5f5;
}
<div class="block">
    <div class="centered">
        <h1>Some text</h1>
        <p>But he stole up to us again, and suddenly clapping his hand on my
           shoulder, said&mdash;"Did ye see anything looking like men going
           towards that ship a while ago?"</p>
    </div>
</div>

Fadi
la source
3
Maintenant -c'est une solution -BRILLIANT-. Merci beaucoup d'avoir posté ceci!
Troy Alford
Comme pour l'autre réponse, celle-ci serait bien meilleure si elle décrivait l'approche et incluait le code du lien.
KatieK
3
+1, cette solution est vraiment assez ingénieuse! Btw vous pouvez ajouter .block { white-space: nowrap; font-size: 0; line-height: 0; }et laisser la marge droite négative sur le pseudo élément, il vous suffit de réinitialiser fs et lh sur .centered ... ainsi vous vous assurez que l'élément sera correctement positionné même s'il est plus large que la fenêtre (et ne 'pas besoin d'utiliser la marge négative imo un peu désordonnée).
Simon
@jessegavin - à votre avis ... comment les éléments suivants se comparent-ils à l'approche que vous avez décrite: stackoverflow.com/questions/396145/…
pulkitsinghal
1
En outre, cela se décompose lorsque le conteneur externe .block a une hauteur min au lieu de hauteur.
Lincoln B
16

C'est quelque chose que j'ai dû faire plusieurs fois et une solution cohérente nécessite toujours d'ajouter un peu de balisage non sémantique et des hacks spécifiques au navigateur. Lorsque nous obtenons le support du navigateur pour css 3, vous obtiendrez votre centrage vertical sans pécher.

Pour une meilleure explication de la technique, vous pouvez consulter l'article à partir duquel je l'ai adaptée , mais cela implique essentiellement d'ajouter un élément supplémentaire et d'appliquer différents styles dans IE et les navigateurs prenant en charge position:table\table-cellles éléments non-table.

<div class="valign-outer">
    <div class="valign-middle">
        <div class="valign-inner">
            Excuse me. What did you sleep in your clothes again last night. Really. You're gonna be in the car with her. Hey, not too early I sleep in on Saturday. Oh, McFly, your shoe's untied. Don't be so gullible, McFly. You got the place fixed up nice, McFly. I have you're car towed all the way to your house and all you've got for me is light beer. What are you looking at, butthead. Say hi to your mom for me.
        </div>
    </div>
</div>

<style>
    /* Non-structural styling */
    .valign-outer { height: 400px; border: 1px solid red; }
    .valign-inner { border: 1px solid blue; }
</style>

<!--[if lte IE 7]>
<style>
    /* For IE7 and earlier */
    .valign-outer { position: relative; overflow: hidden; }
    .valign-middle { position: absolute; top: 50%; }
    .valign-inner { position: relative; top: -50% }
</style>
<![endif]-->
<!--[if gt IE 7]> -->
<style>
    /* For other browsers */
    .valign-outer { position: static; display: table; overflow: hidden; }
    .valign-middle { position: static; display: table-cell; vertical-align: middle; width: 100%; }
</style>

Il existe de nombreuses façons (hacks) d'appliquer des styles dans des ensembles spécifiques de navigateurs. J'ai utilisé des commentaires conditionnels mais regardez l'article lié ci-dessus pour voir deux autres techniques.

Remarque: Il existe des moyens simples d'obtenir un centrage vertical si vous connaissez certaines hauteurs à l'avance, si vous essayez de centrer une seule ligne de texte ou dans plusieurs autres cas. Si vous avez plus de détails, ajoutez-les car il peut y avoir une méthode qui ne nécessite pas de piratage de navigateur ou de balisage non sémantique.

Mise à jour: Nous commençons à obtenir une meilleure prise en charge du navigateur pour CSS3, en apportant à la fois la boîte flexible et les transformations comme méthodes alternatives pour obtenir un centrage vertical (entre autres effets). Voir cette autre question pour plus d'informations sur les méthodes modernes, mais gardez à l'esprit que la prise en charge des navigateurs est encore sommaire pour CSS3.

Prestaul
la source
Oui, j'ai trouvé cet article aujourd'hui et je n'ai pas été en mesure de le faire fonctionner pour ma situation particulière. Je dois peut-être approfondir cette question.
jessegavin le
Peut-être pouvez-vous publier le code que vous utilisez qui ne fonctionne pas?
Chris Marasti-Georg le
Est-ce toujours la meilleure solution à ce problème?
ripper234
Cet article ne semble pas fonctionner sur Chrome 23, Firefox 16 et IE 9. Cette réponse semble être une meilleure solution.
Fernando Correia
Non, cet article fonctionne toujours dans les derniers Chrome et Firefox au 24 février 2013
OMA
9

En utilisant le sélecteur d'enfant, j'ai pris l'incroyable réponse de Fadi ci-dessus et l' ai réduite à une seule règle CSS que je peux appliquer. Il ne me reste plus qu'à ajouter le contentCenterednom de la classe aux éléments que je souhaite centrer:

.contentCentered {
  text-align: center;
}

.contentCentered::before {
  content: '';
  display: inline-block;
  height: 100%; 
  vertical-align: middle;
  margin-right: -.25em; /* Adjusts for spacing */
}

.contentCentered > * {
  display: inline-block;
  vertical-align: middle;
}
<div class="contentCentered">
  <div>
    <h1>Some text</h1>
    <p>But he stole up to us again, and suddenly clapping his hand on my
      shoulder, said&mdash;"Did ye see anything looking like men going
      towards that ship a while ago?"</p>
  </div>
</div>

CodePen fourchu: http://codepen.io/dougli/pen/Eeysg

dougli
la source
Cool. Merci d'avoir partagé. Une mise en garde est que le *sélecteur fonctionnera moins bien que la réponse acceptée. Ce n'est peut-être pas un problème, mais il convient de le noter. stevesouders.com/blog/2009/06/18/simplifying-css-selectors
jessegavin
Merci. Oui, les performances seront probablement pires, mais de nos jours, les règles CSS n'affectent probablement pas beaucoup les choses. Nous pouvons probablement améliorer cela en sélectionnant à la > divplace. calendar.perfplanet.com/2011/…
dougli
Simple et génial. Fonctionne parfaitement pour moi.
Lovro
4

Meilleur résultat pour moi jusqu'à présent:

div pour être centré:

position: absolute;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
right: 0;
left: 0;
Leo Dimuccio
la source
A travaillé comme un charme
m4heshd
3

Vous pouvez utiliser la marge automatique. Avec flex, le div semble également être centré verticalement.

body,
html {
  height: 100%;
  margin: 0;
}
.site {
  height: 100%;
  display: flex;
}
.site .box {
  background: #0ff;
  max-width: 20vw;
  margin: auto;
}
<div class="site">
  <div class="box">
    <h1>blabla</h1>
    <p>blabla</p>
    <p>blablabla</p>
    <p>lbibdfvkdlvfdks</p>
  </div>
</div>
Loïc G.
la source
affichage: flex est encore pratiquement une fonctionnalité expérimentale; aucun navigateur ne le suporte correctement pour le moment
andreszs
1

Pour moi, la meilleure façon de faire est:

.container{
  position: relative;
}

.element{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

L'avantage est de ne pas avoir à rendre la hauteur explicite

Leandro Castro
la source
0

C'est ma solution géniale pour un divavec une hauteur dynamique (en pourcentage).

CSS

.vertical_placer{
  background:red;
  position:absolute; 
  height:43%; 
  width:100%;
  display: table;
}

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

.inner_placer svg{
  position:relative;
  color:#fff;
  background:blue;
  width:30%;
  min-height:20px;
  max-height:60px;
  height:20%;
}

HTML

<div class="footer">
    <div class="vertical_placer">
        <div class="inner_placer">
            <svg> some Text here</svg>
        </div>
    </div>
</div>  

Essayez cela par vous-même.

user3432605
la source
0

vous pouvez utiliser un affichage flexible tel que le code ci-dessous:

.example{
  background-color:red;
  height:90px;
  width:90px;
  display:flex;
  align-items:center; /*for vertically center*/
  justify-content:center; /*for horizontally center*/
}
<div class="example">
    <h6>Some text</h6>
</div>

hassan yousefi
la source