Come centrare verticalmente il contenuto con altezza variabile all'interno di un div?


158

Qual è il modo migliore per centrare verticalmente il contenuto di un div quando l'altezza del contenuto è variabile. Nel mio caso particolare, l'altezza del div del contenitore è fissa, ma sarebbe fantastico se ci fosse una soluzione che funzionerebbe nei casi in cui anche il contenitore ha un'altezza variabile. Inoltre, mi piacerebbe una soluzione senza o con pochissimo uso di hack CSS e / o markup non semantici.

testo alternativo


il metodo in quell'articolo cade in Safari (4.0.5): S

7
@ ripper234 Non esattamente, in quanto questa domanda riguarda div ad altezza variabile
Rauli Rajande

9
Inoltre, questa domanda è stata posta per prima.
Gui Imamura,

Risposte:


147

Basta aggiungere

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

al div interno.

Ciò che fa è spostare il bordo superiore del div interno a metà altezza del div esterno ( top: 50%;) e quindi il div interno in alto di metà della sua altezza ( transform: translateY(-50%)). Questo funzionerà con position: absoluteo relative.

Tienilo a mente transforme translatedisponi di prefissi dei fornitori che non sono inclusi per semplicità.

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


6
Mi chiedevo solo perché questo funziona su Chrome e Firefox, ma non per Safari. Poi ho notato che la maggior parte transformdelle cose correlate ha il -webkit-prefisso e ora funziona. Quindi, come promemoria: non dimenticare di aggiungere anche il -webkit-prefisso.
miho,

5
Utilizza uno strumento come github.com/postcss/autoprefixer per gestire i prefissi per te.
Jamie Chong,

6
Questa risposta dovrebbe essere al top.
Jose Faeti,

3
Questo dovrebbe avere molti più voti! A proposito, funziona anche con position: absolute, no?
Caw

4
Questo metodo ha uno sfortunato effetto collaterale in Chrome: se il tuo wrapper ha un numero dispari di pixel translate, renderà tutto sfocato mentre cerca di gestire l'altezza .5px su tutto.
Keith,

157

Questa sembra essere la migliore soluzione che ho trovato a questo problema, purché il tuo browser supporti lo ::beforepseudo elemento: CSS-Tricks: Centering in the Unknown .

Non richiede alcun markup aggiuntivo e sembra funzionare molto bene. Non ho potuto usare il display: tablemetodo perché gli tableelementi non obbediscono alla max-heightproprietà.

.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>


3
Ora, quella è una soluzione BRILLANTE. Grazie mille per aver pubblicato questo!
Troy Alford,

Come con l'altra risposta, questa sarebbe molto meglio se descrivesse l'approccio e includesse il codice dal link.
KatieK,

3
+1, questa soluzione è davvero abbastanza geniale! Tra l'altro potresti aggiungere .block { white-space: nowrap; font-size: 0; line-height: 0; }e lasciare il margine destro negativo sullo pseudo elemento, devi solo resettare fs e lh su .centered ... in questo modo ti assicuri che l'elemento sarà posizionato correttamente anche se è più largo del viewport (e don dovrei usare il margine negativo un po 'disordinato di imo).
Simon,

@jessegavin - secondo te ... come fa il seguente stack contro l'approccio che ho descritto: stackoverflow.com/questions/396145/...
pulkitsinghal

1
Inoltre, ciò si interrompe quando il blocco esterno del contenitore ha un'altezza minima anziché un'altezza.
Lincoln B,

16

Questo è qualcosa che ho dovuto fare molte volte e una soluzione coerente richiede ancora di aggiungere un po 'di markup non semantico e alcuni hack specifici del browser. Quando avremo il supporto del browser per css 3 otterrai il tuo centraggio verticale senza peccare.

Per una migliore spiegazione della tecnica è possibile consultare l'articolo da cui l'ho adattato , ma in pratica comporta l'aggiunta di un elemento aggiuntivo e l'applicazione di stili diversi in Internet Explorer e browser che supportano position:table\table-cellelementi non di tabella.

<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>

Esistono molti modi (hack) per applicare gli stili in set specifici di browser. Ho usato i commenti condizionali, ma guarda l'articolo collegato sopra per vedere altre due tecniche.

Nota: ci sono modi semplici per ottenere il centramento verticale se si conoscono alcune altezze in anticipo, se si sta tentando di centrare una singola riga di testo o in molti altri casi. Se hai maggiori dettagli, inseriscili perché potrebbe esserci un metodo che non richiede hack del browser o markup non semantico.

Aggiornamento: stiamo iniziando a ottenere un migliore supporto del browser per CSS3, portando sia flex-box che trasformazioni come metodi alternativi per ottenere il centraggio verticale (tra gli altri effetti). Vedi questa altra domanda per ulteriori informazioni sui metodi moderni, ma tieni presente che il supporto del browser è ancora impreciso per CSS3.


Sì, ho trovato quell'articolo oggi e non sono stato in grado di farlo funzionare per la mia situazione particolare. Forse devo approfondire ulteriormente.
jessegavin,

Forse puoi pubblicare il codice che stai utilizzando che non funziona?
Chris Marasti-Georg,

È ancora la soluzione migliore per questo problema?
ripper234,

L'articolo non sembra funzionare su Chrome 23, Firefox 16 e IE 9. Questa risposta sembra essere una soluzione migliore.
Fernando Correia,

No, quell'articolo funziona ancora negli ultimi Chrome e Firefox al 24 febbraio 2013
OMA,

9

Usando il selettore figlio, ho preso l'incredibile risposta di Fadi sopra e l'ho ridotta a una sola regola CSS che posso applicare. Ora tutto ciò che devo fare è aggiungere il contentCenterednome della classe agli elementi che voglio centrare:

.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>

Codice Forked: http://codepen.io/dougli/pen/Eeysg


Freddo. Grazie per la condivisione. Una nota di cautela è che il *selettore funzionerà peggio della risposta accettata. Potrebbe non essere un problema, ma vale la pena notare. stevesouders.com/blog/2009/06/18/simplifying-css-selectors
jessegavin,

Grazie. Sì, probabilmente funzionerà peggio, ma al giorno d'oggi le regole CSS probabilmente non influenzano molto le cose. Probabilmente possiamo migliorare questo selezionando > divinvece. calendar.perfplanet.com/2011/…
dougli

Semplice e fantastico. Funziona perfettamente per me.
Lovro,

4

Il miglior risultato per me finora:

div da centrare:

position: absolute;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
right: 0;
left: 0;

Ha funzionato come un fascino
m4heshd

3

È possibile utilizzare il margine automatico. Con flex, anche il div sembra essere centrato verticalmente.

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>

display: flex è ancora praticamente una caratteristica sperimentale; nessun browser lo supporta ancora correttamente
andreszs

1

Per me il modo migliore per farlo è:

.container{
  position: relative;
}

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

Il vantaggio non è di rendere esplicita l'altezza


0

Questa è la mia fantastica soluzione per divun'altezza dinamica (in percentuale).

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>  

Prova questo da solo.


0

puoi usare il display flessibile come il codice seguente:

.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>

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.