Jak wyśrodkować w pionie zawartość o zmiennej wysokości w elemencie DIV?

158

Jaki jest najlepszy sposób na wyśrodkowanie zawartości elementu div w pionie, gdy wysokość zawartości jest zmienna. W moim przypadku wysokość elementu div kontenera jest stała, ale byłoby świetnie, gdyby istniało rozwiązanie, które sprawdzi się w przypadkach, gdy kontener ma również zmienną wysokość. Chciałbym również rozwiązania bez lub z niewielkim wykorzystaniem hacków CSS i / lub nieemantycznych znaczników.

tekst alternatywny

jessegavin
źródło
metoda opisana w tym artykule nie działa w Safari (4.0.5): S
7
@ ripper234 Niezupełnie, ponieważ to pytanie dotyczy zmiennej wysokości div
Rauli Rajande
9
Również to pytanie zostało zadane jako pierwsze.
Gui Imamura

Odpowiedzi:

147

Poprostu dodaj

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

do wewnętrznego div.

To, co robi, to przesunięcie górnej granicy wewnętrznego elementu div na połowę wysokości elementu div zewnętrznego ( top: 50%;), a następnie elementu div w górę o połowę jego wysokości ( transform: translateY(-50%)). To zadziała z position: absolutelub relative.

Należy o tym pamiętać transformi translatemieć przedrostki dostawców, które nie zostały uwzględnione dla uproszczenia.

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

BlackCetha
źródło
6
Zastanawiałem się tylko, dlaczego to działa w Chrome i Firefox, ale nie w Safari. Potem zauważyłem, że większość transformpowiązanych rzeczy ma -webkit-prefiks i teraz działa. A więc dla przypomnienia: nie zapomnij dodać również -webkit-przedrostka.
miho
5
Użyj narzędzia takiego jak github.com/postcss/autoprefixer, aby obsłużyć prefiksy za Ciebie.
Jamie Chong
6
Ta odpowiedź powinna znajdować się u góry.
Jose Faeti
3
To powinno mieć znacznie więcej głosów pozytywnych! Nawiasem mówiąc, to też działa position: absolute, prawda?
krakaj
4
Ta metoda ma niefortunny efekt uboczny w Chrome - jeśli twój wrapper ma nieparzystą liczbę pikseli, wtedy translatewszystko będzie zamazane, gdy spróbuje obsłużyć wysokość .5px na wszystkim.
Keith
157

Wydaje się, że jest to najlepsze rozwiązanie tego problemu, jakie znalazłem, o ile Twoja przeglądarka obsługuje ::beforepseudoelement: CSS-Tricks: Centering in the Unknown .

Nie wymaga żadnych dodatkowych znaczników i wydaje się działać wyjątkowo dobrze. Nie mogłem użyć tej display: tablemetody, ponieważ tableelementy nie są zgodne z max-heightwłaściwością.

.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
źródło
3
Teraz -to- jest -BRILLIANT- rozwiązanie. Dziękuję bardzo za opublikowanie tego!
Troy Alford,
Podobnie jak w przypadku drugiej odpowiedzi, ta byłaby znacznie lepsza, gdyby opisywała podejście i zawierała kod z linku.
KatieK,
3
+1, To rozwiązanie jest naprawdę genialne! Przy okazji możesz dodać .block { white-space: nowrap; font-size: 0; line-height: 0; }i pozostawić ujemny prawy margines na pseudoelemencie, po prostu musisz zresetować fs i lh on .centrered ... w ten sposób upewniasz się, że element zostanie poprawnie umieszczony, nawet jeśli jest szerszy niż widok (i nie nie muszę używać imo trochę niechlujnego ujemnego marginesu).
Simon,
@jessegavin - Twoim zdaniem ... w jaki sposób następujące elementy wypadają w porównaniu z podejściem, które przedstawiłeś: stackoverflow.com/questions/396145/ ...
pulkitsinghal
1
Również to psuje się, gdy zewnętrzny kontener .block ma minimalną wysokość zamiast wysokości.
Lincoln B
16

To jest coś, co musiałem zrobić wiele razy, a spójne rozwiązanie nadal wymaga dodania niewielkiego niesemantycznego znacznika i kilku hacków specyficznych dla przeglądarki. Kiedy otrzymamy obsługę CSS 3 przez przeglądarkę, uzyskasz wyśrodkowanie w pionie bez grzechu.

Aby lepiej wyjaśnić tę technikę, możesz zajrzeć do artykułu, z którego ją zaadaptowałem , ale w zasadzie obejmuje to dodanie dodatkowego elementu i zastosowanie różnych stylów w IE i przeglądarkach, które obsługują position:table\table-cellelementy inne niż tabele.

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

Istnieje wiele sposobów (hacków) stosowania stylów w określonych zestawach przeglądarek. Użyłem komentarzy warunkowych, ale spójrz na powyższy artykuł, aby zobaczyć dwie inne techniki.

Uwaga: wyśrodkowanie w pionie można uzyskać w prosty sposób, jeśli znasz jakieś wysokości z wyprzedzeniem, próbujesz wyśrodkować pojedynczy wiersz tekstu lub w kilku innych przypadkach. Jeśli masz więcej szczegółów, wrzuć je, ponieważ może istnieć metoda, która nie wymaga hacków przeglądarki ani nie-semantycznych znaczników.

Aktualizacja: Zaczynamy otrzymywać lepszą obsługę przeglądarki CSS3, wprowadzając zarówno flex-box, jak i transformacje jako alternatywne metody uzyskiwania wyśrodkowania w pionie (między innymi). Zobacz to drugie pytanie, aby uzyskać więcej informacji o nowoczesnych metodach, ale pamiętaj, że obsługa przeglądarek jest nadal szkicowa dla CSS3.

Prestaul
źródło
Tak, znalazłem dzisiaj ten artykuł i nie byłem w stanie dopasować go do mojej konkretnej sytuacji. Być może muszę przyjrzeć się temu dokładniej.
jessegavin
Może możesz opublikować kod, którego używasz, a który nie działa?
Chris Marasti-Georg,
Czy to nadal najlepsze rozwiązanie tego problemu?
ripper234
Ten artykuł nie działa w przeglądarce Chrome 23, Firefox 16 i IE 9. Ta odpowiedź wydaje się być lepszym rozwiązaniem.
Fernando Correia
Nie, ten artykuł nadal DZIAŁA w najnowszych przeglądarkach Chrome i Firefox od 24 lutego 2013 r.
OMA
9

Korzystając z selektora dziecka, wziąłem powyżej niesamowitą odpowiedź Fadiego i sprowadziłem ją do jednej reguły CSS, którą mogę zastosować. Teraz wszystko, co muszę zrobić, to dodać contentCenterednazwę klasy do elementów, które chcę wyśrodkować:

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

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

dougli
źródło
Chłodny. Dzięki za udostępnienie. Należy pamiętać, że *selektor będzie działał gorzej niż zaakceptowana odpowiedź. To może nie być problem, ale warto zwrócić uwagę. stevesouders.com/blog/2009/06/18/simplifying-css-selectors
jessegavin
Dzięki. Tak, prawdopodobnie będzie działać gorzej, ale obecnie reguły CSS prawdopodobnie nie mają większego wpływu na rzeczy. Prawdopodobnie możemy to poprawić, wybierając > divzamiast tego. calendar.perfplanet.com/2011/…
dougli
Proste i świetne. U mnie działa idealnie.
Lovro,
4

Jak dotąd najlepszy wynik dla mnie:

div do wyśrodkowania:

position: absolute;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
right: 0;
left: 0;
Leo Dimuccio
źródło
Działał jak urok
m4heshd
3

Możesz użyć automatycznego marginesu. W przypadku flex, element div wydaje się być również wyśrodkowany w pionie.

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.
źródło
display: flex jest nadal praktycznie funkcją eksperymentalną; żadna przeglądarka nie obsługuje go poprawnie
andreszs
1

Dla mnie najlepszym sposobem na to jest:

.container{
  position: relative;
}

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

Zaletą jest brak konieczności wyraźnego określania wysokości

Leandro Castro
źródło
0

To jest moje niesamowite rozwiązanie dla div z dynamiczną (procentową) wysokością.

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>  

Spróbuj sam.

user3432605
źródło
0

możesz użyć wyświetlacza flex, takiego jak poniższy kod:

.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
źródło