Korzystanie z marginesu: auto do wyrównania div w pionie


113

Wiem więc, że możemy wyśrodkować element div w poziomie, jeśli użyjemy margin:0 auto;. Powinien margin:auto auto;działać tak, jak myślę, że powinien działać? Centrowanie również w pionie?

Dlaczego też nie vertical-align:middle;działa?

.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
Gorąco sugeruję przeczytanie i wdrożenie poniższej odpowiedzi @ zpr dotyczącej Flexbox. Na dzień dzisiejszy jest on dość dobrze obsługiwany, a Twój css będzie znacznie, dużo czystszy.
Govind Rai

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

Odpowiedzi:


173

Zaktualizuj sierpień 2020 r

Chociaż poniżej warto przeczytać przydatne informacje, od jakiegoś czasu mamy Flexbox, więc po prostu użyj go, zgodnie z tą odpowiedzią .


Nie możesz użyć:

vertical-align:middleponieważ nie ma zastosowania do elementów blokowych

margin-top:autoi margin-bottom:autoponieważ ich używane wartości byłyby obliczane jako zero

margin-top:-50%ponieważ procentowe wartości marginesów są obliczane w odniesieniu do szerokości bloku zawierającego

W rzeczywistości charakter przepływu dokumentów i algorytmy obliczania wysokości elementu uniemożliwiają użycie marginesów do wyśrodkowania elementu w pionie wewnątrz jego elementu nadrzędnego. Za każdym razem, gdy wartość marginesu pionowego zostanie zmieniona, spowoduje to ponowne obliczenie wysokości elementu nadrzędnego (ponowne przepływ), co z kolei spowoduje ponowne wyśrodkowanie oryginalnego elementu ... czyniąc go nieskończoną pętlą.

Możesz użyć:

Kilka podobnych obejść, które działają w Twoim scenariuszu; trzy elementy muszą być zagnieżdżone w następujący sposób:

.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

Według Browsershot JSFiddle działa dobrze.


10
#to sztuczka polegająca na tym, że reguła poprzedzona jest prefiksem, interpretowana tylko przez IE7 i poniżej. Możesz zamiast tego zawrzeć te reguły w arkuszu stylów specyficznym dla IE, używając komentarzy warunkowych itp.
dniu

2
+1 ze względu na powody, dla których tak się dzieje, obliczenie procentu marginesu na podstawie szerokości bardzo otworzyło oczy.
ricosrealm

2
Wątpię w stwierdzenie „nieskończona pętla”.
Barun,

105
ludzkość była już na Księżycu wiele lat temu i wciąż mamy do czynienia z tą bzdurą. wyrównywanie rzeczy w pionie w przeglądarce, jesus
user151496

3
W wieku> = IE9 position: absolute; top: 50%; transform: translateY(-50%);jest również wykonalne i dość popularne ... (w przeciwieństwie top:50%;margin: - $halfHeightdo tego, że nie musisz znać wysokości z góry ...)
Frank Nocke

112

Ponieważ to pytanie zostało zadane w 2012 roku i przeszliśmy długą drogę dzięki obsłudze flexboxów przez przeglądarki, czułem, że ta odpowiedź jest obowiązkowa.

Jeśli wyświetlanie kontenera nadrzędnego to flex, to tak , margin: auto auto(znanego również jako margin: auto) będzie działać, aby wyśrodkować go zarówno w poziomie, jak iw pionie, niezależnie od tego, czy jest to element inlineczy 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>

Zauważ, że szerokość / wysokość nie muszą być określane absolutnie, jak w tym przykładzie jfiddle, który używa rozmiaru w stosunku do widocznego obszaru.

Chociaż wsparcie przeglądarek dla flexboxów jest na najwyższym poziomie w momencie publikowania, wiele przeglądarek nadal nie obsługuje tego lub wymaga prefiksów dostawców. Odwiedź http://caniuse.com/flexbox, aby uzyskać aktualne informacje o obsłudze przeglądarek.

Aktualizacja

Ponieważ ta odpowiedź zwróciła trochę uwagi, chciałbym również zwrócić uwagę, że nie musisz marginw ogóle określać, czy używasz display: flexi chcesz wyśrodkować wszystkie elementy w kontenerze:

#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
rodzic {display: flex; } child {margin: auto 0; } jest po prostu świetny.
Arek Kostrzeba

OMG stary, jesteś gwiazdą rocka, cholera, nie mogę cię więcej niż raz głosować !!!
PirateApp

To dobra odpowiedź, gdy możesz być również zdezorientowany z problemem dopasowania treści. Ustawiając flex w kontenerze, element div zawartości nie potrzebuje żadnych właściwości do ustawienia.
Eric,

1
To zdecydowanie najlepsze i eleganckie rozwiązanie do pracy w 2018 roku, dziękuję.
SilverSurfer

Dodam, że od maja 2018 r. Przy takim rozwiązaniu tekst nie wyrównuje się w pionie do środka w IE 11.
Yefu

62

Oto najlepsze rozwiązanie, jakie znalazłem: http://jsfiddle.net/yWnZ2/446/ Działa w Chrome, Firefox, Safari, IE8-11 i Edge.

Jeśli zadeklarowana height( height: 1em, height: 50%, itd.), Albo jest to element, w którym przeglądarka zna wysokość ( img, svglub canvasna przykład), to wszystko, czego potrzebujesz do centrowania pionowego jest to:

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

Zwykle będziesz chciał określić widthlub max-widthtak, aby zawartość nie rozciągała się na całej długości ekranu / kontenera.

Jeśli używasz tego dla modalu, który ma być zawsze wyśrodkowany w widocznym obszarze, nakładając się na inną zawartość, użyj position: fixed;dla obu elementów zamiast position: absolute. http://jsfiddle.net/yWnZ2/445/

Oto bardziej kompletny opis: http://codepen.io/shshaw/pen/gEiDt


3
To niekoniecznie wyśrodkowuje go w swoim elemencie nadrzędnym. Niezły hack, jeśli chcesz go po prostu umieścić na środku strony.
Joel Mellon

2
Po prostu dodaj position: relativedo rodzica, a element zostanie wyśrodkowany w rodzicu. Napisałem dużo więcej w Smashing Magazine na temat tej techniki, jeśli chcesz przeczytać więcej: coding.smashingmagazine.com/2013/08/09/…
shshaw

Czasami wartość bezwzględna opiera się na rodzicu lub dwóch starszych (w porównaniu z ciałem), a krewny może być dziadkiem lub pradziadkiem (w porównaniu z rodzicem). Może ci, którzy wiedzą, kiedy lub dlaczego tak się dzieje, mogliby lepiej kontrolować tę technikę - nigdy tak naprawdę nie badałem tych kwestii, ale wiem, że przejście z wartości bezwzględnej na względną nie jest samo w sobie rozwiązaniem, które sprawi, że ta zadziała. Czytałem trochę twojego artykułu i wygląda na to, że absolutne i względne idą w górę do pierwszego absolutnego lub względnego przodka, czy to prawda?
Joel Mellon

Jestem trochę wolny. Właśnie ponownie przeczytałem twój komentarz powyżej. Nie zauważyłem, że powiedziałeś, żeby dodać to do parent- rozumiem . Dzięki wielkie!
Joel Mellon

1
@commonpike Jedynym problemem z IE8 / 9 jest to, że używasz display: tabledo treści o zmiennej wysokości. W przeciwnym razie ta metoda powinna działać zgodnie z oczekiwaniami. Przeczytaj opis, aby uzyskać więcej informacji. Powinieneś także móc przetestować pełny widok w IE8 / 9, aby sprawdzić, czy są jakieś problemy.
shshaw

22

Edycja: jest rok 2020, zamiast tego użyłbym flex box.

Oryginalna odpowiedź:

HTML

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

CSS

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

nie będzie działać dla IE 8 i starszych wersji IE. Ponieważ właściwość transformacji jest obsługiwana (z przedrostkiem -ms-) od wersji 9.0 i nowszych. (tj. 10 nie potrzebuje już prefiksu).
DevWL

5
To prawda, nie obchodzi mnie IE8
Gal Margalit

A pisarz oznaczył html5 dla swojego pytania ☺
Gal Margalit,

9

Wiem, że pytanie pochodzi z 2012 roku, ale znalazłem najłatwiejszą drogę i chciałem się nim podzielić.

HTML:

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

i CSS:

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

7

Jeśli znasz wysokość elementu div, który chcesz wyśrodkować , możesz ustawić go absolutnie wewnątrz jego elementu nadrzędnego, a następnie ustawić topwartość na 50%. Spowoduje to, że górna część elementu podrzędnego div będzie o 50% niższa od elementu nadrzędnego, czyli będzie za nisko. Pociągnij go z powrotem, ustawiając go margin-topna połowę jego wysokości. Więc teraz masz pionowy punkt środkowy elementu div dziecka znajdujący się w pionowym punkcie środkowym rodzica - wyśrodkowany w pionie!

Przykład:

.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-topnie można ustawić w% w stosunku do wysokości elementu, więc otrzymasz poprawkę zależną od wymiarów
ov

1
Co jest… dokładnie tym, co powiedziałem w mojej odpowiedzi? „Jeśli znasz wysokość elementu div, który chcesz wyśrodkować”. I nie powiedziałem, że OP powinien używać% w margin-top.
tuf,

Nie zgadzam się z rozwiązaniem, ponieważ blokuje Cię na wcześniej zdefiniowanej wysokości elementu - ale Twój komentarz ma sens. Możesz odzwierciedlać odpowiedź
ov

3
OK, pogrubiłem część, którą przeoczyłeś, mam nadzieję, że teraz jest to jaśniejsze.
tuf

1
@ov: Jeśli element nie ma ustalonej wysokości, możesz po prostu użyć JS, aby uzyskać obliczoną wysokość, a następnie odpowiednio ustawić ujemny górny margines. Moim zdaniem jest to nadal najlepsza metoda centrowania w pionie.
daGUY,

3

Te dwa rozwiązania wymagają tylko dwóch zagnieżdżonych elementów.
Po pierwsze - pozycjonowanie względne i bezwzględne, jeśli treść jest statyczna (wyśrodkowanie ręczne).

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

lub do projektowania płynnego - zamiast tego użyj poniższego przykładu dla dokładnego centrum treści:

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

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

Musisz ustawić minimalną wysokość na wypadek, gdyby zawartość przekroczyła 50% wysokości okna. Możesz również manipulować tą wysokością za pomocą zapytania o media dla urządzeń mobilnych i tabletów. Ale tylko jeśli bawisz się responsywnym designem.

Myślę, że możesz pójść dalej i użyć prostego skryptu JavaScript / JQuery do manipulowania minimalną lub stałą wysokością, jeśli z jakiegoś powodu jest taka potrzeba.

Po drugie - jeśli zawartość jest płynna, możesz również użyć właściwości CSS tabeli i komórki tabeli z wyrównaniem w pionie i wyśrodkowaniem tekstu:

/*in a wrapper*/  
display:table;   

i

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

Doskonale działa i skaluje się, często używane jako elastyczne rozwiązanie do projektowania witryn internetowych z układami siatki i zapytaniami o media, które manipulują szerokością obiektu.

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

Preferuję rozwiązanie tabelaryczne do dokładnego wyśrodkowania treści, ale w niektórych przypadkach względne pozycjonowanie bezwzględne będzie lepsze, zwłaszcza jeśli nie chcemy zachować dokładnej proporcji wyrównania treści.


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>


Czy mógłbyś podzielić się z nami, na czym polega to rozwiązanie? Poza tym widzę twój „wyskakujący komunikat” na dole nie wyśrodkowany
Alex

Coś mi umknęło, ale teraz zostało ulepszone, aby utrzymać element div na środku w pionie. możesz sprawdzić teraz.
Seetpal singh

0

Nie ma jednego prostego sposobu wyśrodkowania elementu div w pionie, który wystarczyłby w każdej sytuacji.

Jest jednak na to wiele sposobów w zależności od sytuacji.

Oto kilka z nich:

  • Ustaw dopełnienie od góry i dołu elementu nadrzędnego, na przykład dopełnienie: 20px 0px 20px 0px
  • Użyj tabeli, komórka tabeli wyśrodkuje zawartość w pionie
  • Ustaw względną pozycję elementu nadrzędnego oraz element div, który chcesz wyśrodkować w pionie, na wartość bezwzględną i ustaw styl jako górny: 50px; dół: 50px; na przykład

Możesz także wyszukać w Google hasło „wyśrodkowanie w pionie css”


0

zmienna wysokość, automatyczne górne i dolne marginesy

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

zmienna wysokość, automatyczne górne i dolne marginesy


0

Korzystanie z 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 */
}

Zobaczyć wynik


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>
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.