Използване на margin:auto за вертикално подравняване на div

Знам, че можем да центрираме div хоризонтално, ако използваме margin:0 auto;. Трябва ли margin:auto auto; да работи както смятам, че трябва да работи? Да го центрирате и вертикално?

Защо и vertical-align:middle; не работи?

.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


person savinger    schedule 13.09.2012    source източник
comment
Силно препоръчваме да прочетете и приложите отговора на @zpr по-долу относно Flexbox. Поддържа се доста добре от днес и вашият css ще бъде много, много по-чист.   -  person Govind Rai    schedule 01.01.2017
comment
if((new Date()).getFullYear() › 2017) useFlexBox = true;   -  person brandito    schedule 05.04.2018


Отговори (12)


Актуализация август 2020

Въпреки че все още си струва да прочетете по-долу за полезна информация, имаме Flexbox от известно време, така че просто го използвайте, според този отговор.


Не можете да използвате:

vertical-align:middle защото това не е< /em> приложимо към елементи на ниво блок

margin-top:auto и margin-bottom:auto, защото използваните им стойности биха се изчислили като нула

margin-top:-50% тъй като процентно базираните марж стойности се изчисляват спрямо ширина на съдържащия се блок

Всъщност естеството на документния поток и алгоритмите за изчисляване на височината на елемент го правят невъзможно е да се използват полета за центриране на елемент вертикално вътре в неговия родител. Всеки път, когато стойността на вертикален марж се промени, това ще задейства повторно изчисляване на височината на родителския елемент (re-flow), което на свой ред ще задейства повторно центриране на оригиналния елемент... което го прави безкраен цикъл.

Можете да използвате:

Няколко заобиколни решения като това, които работят за вашия сценарий; трите елемента трябва да бъдат вложени така:

.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 работи добре според Browsershot.

person Oleg    schedule 14.09.2012
comment
Благодаря! Първите три бележки са много полезни за познаване. Бърз въпрос... знаците за паунд във вашия css просто коментари ли са? - person savinger; 14.09.2012
comment
# е хак да има префикс на правилото, интерпретиран само от IE7 и под. Може вместо това да предпочетете да включите тези правила в специфичен за IE стилов лист като използвате условни коментари и т.н. - person Oleg; 15.09.2012
comment
+1 за цитирането на причините, поради които случаят е такъв, изчисляването на процента на маржа въз основа на ширината беше много впечатляващо. - person ricosrealm; 10.03.2013
comment
Отлично, точно това, от което имах нужда. Връщам се към добрата стара маса, но по css начин. Просто се опитвах да направя същото с flex box, успях, но поддръжката му е толкова нестабилна, че трябваше да измисля друг подход. - person JorgeeFG; 17.04.2013
comment
Съмнявам се относно твърдението за „безкраен цикъл“. - person Barun; 11.06.2014
comment
Има по-нов и по-кратък отговор. - person Qwerty; 09.04.2015
comment
човечеството вече е било на Луната преди години и все още трябва да се справяме с тези глупости. вертикално подравняване на нещата в браузър, Исусе - person user151496; 11.05.2015
comment
КОРЕКЦИЯ: .content трябва display: table; да се центрира .. благодаря.. работи - person KingRider; 23.10.2015
comment
@KingRider Не използвайте таблици за оформление. - person TylerH; 11.08.2016
comment
@TylerH проблем моят bootstrap конфликт. Ами случи се. - person KingRider; 11.08.2016
comment
В ›= IE9 ерата, position: absolute; top: 50%; transform: translateY(-50%); също е осъществимо и доста популярно... (за разлика от top:50%;margin: - $halfHeight не е нужно да знаете височината предварително...) - person Frank Nocke; 09.04.2017
comment
Ако идвате на този въпрос след 2019 г., моля, погледнете по-долу за по-добър отговор, който разглежда FlexBox като начин за това. - person clayRay; 03.07.2020

Тъй като този въпрос беше зададен през 2012 г. и ние изминахме дълъг път с поддръжката на браузъра за flexboxes, почувствах, че този отговор е задължителен.

Ако дисплеят на вашия родителски контейнер е flex, тогава да, margin: auto auto (известен също като margin: auto) ще работи, за да го центрира както хоризонтално, така и вертикално, независимо дали е inline или 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>

Обърнете внимание, че ширината/височината не трябва да се посочва абсолютно, както в този примерен jfiddle, който използва оразмеряване спрямо прозореца за изглед.

Въпреки че поддръжката на браузъра за flexboxes е най-висока за всички времена към момента на публикуване, много браузъри все още не го поддържат или изискват префикси на доставчика. Обърнете се към http://caniuse.com/flexbox за актуализирана информация за поддръжка на браузъра.

Актуализация

Тъй като този отговор получи малко внимание, бих искал също да отбележа, че изобщо не е необходимо да указвате margin, ако използвате display: flex и искате да центрирате всички елементи в контейнера:

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

person zpr    schedule 27.09.2014
comment
родител { дисплей: flex; } дете { margin: auto 0; } е просто страхотно. - person Arek Kostrzeba; 02.12.2016
comment
OMG пич, ти си рок звезда, по дяволите, не мога да гласувам повече от веднъж за теб!!! - person PirateApp; 15.12.2017
comment
Това е добър отговор, когато може също да бъдете объркани с проблема с подходящото съдържание. Като зададете flex на контейнера, div съдържанието не се нуждае от никакви свойства за настройване. - person Eric; 09.02.2018
comment
Това определено е най-доброто и елегантно решение за работа през 2018 г., благодаря ви. - person SilverSurfer; 24.02.2018
comment
Бих искал да добавя, че от май 2018 г. с това решение текстът не се подравнява вертикално в средата в IE 11. - person Yefu; 31.05.2018
comment
Най-доброто решение през 2020 г., също и между браузъри - person scravy; 20.07.2020

Ето най-доброто решение, което намерих: http://jsfiddle.net/yWnZ2/446/ Работи в Chrome, Firefox, Safari, IE8-11 и Edge.

Ако имате деклариран height (height: 1em, height: 50% и т.н.) или това е елемент, при който браузърът знае височината (img, svg или canvas например), тогава всичко, от което се нуждаете за вертикално центриране, е следното:

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

Обикновено ще искате да посочите width или max-width, така че съдържанието да не се простира по цялата дължина на екрана/контейнера.

Ако използвате това за модал, който искате винаги да е центриран в прозореца за изглед, припокриващ друго съдържание, използвайте position: fixed; и за двата елемента вместо position: absolute. http://jsfiddle.net/yWnZ2/445/

Ето по-пълен текст: http://codepen.io/shshaw/pen/gEiDt

person shshaw    schedule 07.08.2013
comment
Това не го центрира непременно в неговия родителски елемент. Добър хак, ако просто го искате в центъра на страницата. - person Joel Mellon; 24.01.2014
comment
Просто добавете position: relative към родителя и елементът ще бъде центриран в родителя. Направих много по-голямо описание на Smashing Magazine за техниката, ако искате да прочетете повече: coding.smashingmagazine.com/2013/08/09/ - person shshaw; 24.01.2014
comment
Понякога абсолютното се основава на родител или два нагоре (срещу тялото), а роднината може да бъде прародител или прабаба (срещу родителя). Може би тези, които знаят кога или защо се случва това, биха могли да контролират тази техника по-добре - никога не съм разглеждал тези проблеми, но знам, че преминаването от абсолютно към относително само по себе си не е решение, което да направи тази работа. Прочетох малко от вашата статия и изглежда, че абсолютният и относителният стигат до първия абсолютен или относителен прародител, така ли е? - person Joel Mellon; 24.01.2014
comment
Аз съм малко бавен. Просто препрочетох коментара ти по-горе. Не забелязах, че казахте да го добавите към parent - разбрах. Много благодаря! - person Joel Mellon; 24.01.2014
comment
Да, това е! position: absolute елементите винаги се позиционират въз основа на най-близкия position: relative родител. - person shshaw; 25.01.2014
comment
Определено най-добрият начин. - person APAD1; 06.08.2014
comment
Може ли някой да ни каже за предупрежденията за ie8/9 или да даде връзка към документ, който ги описва? - person commonpike; 18.03.2016
comment
@commonpike Единственият проблем с IE8/9 е, ако използвате display: table за съдържание с променлива височина. В противен случай този метод трябва да работи според очакванията. Прочетете запис за повече подробности като цяло. Трябва също да можете да тествате пълния изглед в IE8/9, за да видите дали има всякакви проблеми. - person shshaw; 18.03.2016
comment
2017. Подходът не работи в IE10+ (няма вертикално или хоризонтално подравняване) или Firefox 52 (само хоризонтално подравняване), емулацията на IE9 не поддържа jsfiddle, така че не може да тества по-ранни версии, ако IE. Работи в Chrome 57 (както вертикално, така и хоризонтално). - person Neolisk; 18.04.2017
comment
@Neolisk Този метод работи стабилно обратно към IE8/9, стига да декларирате височина ( height: 50%, height: 100px, height: 0; padding-top: 50% ) или височината автоматично се знае от браузъра ( img, svg и canvas елементи и т.н.). Хакът display: table не работи добре между различни браузъри, но предоставянето на височина трябва да работи без проблеми. Вижте пълния текст за повече информация: codepen.io/shshaw/pen/gEiDt - person shshaw; 18.04.2017
comment
@shshaw: Да, последният ти пример работи във всички браузъри, изглежда, но е доста сложен. Jsfiddle в отговора има проблеми, бихте ли го актуализирали, така че да работи във всички браузъри? Моля, поддържайте го възможно най-просто. Един празен div, пълен с плътен цвят, е достатъчен за демонстрация. - person Neolisk; 18.04.2017
comment
@Neolisk Оригиналният Fiddle се основава на точните нужди на оригиналния аскер. Единствените необходими части за центриране са position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; и height. Актуализирах FIddle, за да бъде малко по-прост: jsfiddle.net/yWnZ2/445 - person shshaw; 18.04.2017

Редактиране: 2020 г. е, вместо това бих използвал flex box.

Оригинален отговор:

Html

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

CSS

.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
person Gal Margalit    schedule 19.07.2015
comment
няма да работи за IE 8 и по-стари версии на ie. Тъй като свойството на трансформация се поддържа (с префикс -ms-) от версия 9.0 и по-нова. (т.е. 10 вече не се нуждае от префикс). - person DevWL; 01.09.2015
comment
Вярно, не ми пука за IE8 - person Gal Margalit; 01.09.2015
comment
И писателят тагна html5 за своя въпрос ☺ - person Gal Margalit; 06.09.2015

Знам, че въпросът е от 2012 г., но намерих най-лесния начин и исках да споделя.

HTML:

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

и CSS:

#parent{
     height: 100%;
     display: table;
}    
#child {
     display: table-cell;
     vertical-align: middle; 
}
person Paula Fleck    schedule 17.09.2014

Ако знаете височината на div, който искате да центрирате, можете да го позиционирате абсолютно в неговия родител и след това да зададете стойността top на 50%. Това ще постави горната част на дъщерния div на 50% надолу от неговия родител, т.е. твърде ниско. Издърпайте го обратно нагоре, като настроите margin-top на половината му височина. Така че сега имате вертикалната средна точка на дъщерния div, разположена във вертикалната средна точка на родителя - вертикално центрирано!

Пример:

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

person tuff    schedule 13.09.2012
comment
margin-top не може да бъде зададено в % спрямо височината на елемента, така че в крайна сметка ще получите корекция, зависима от размерите - person Oleg; 14.09.2012
comment
Което е...точно това, което казах в отговора си? Ако знаете височината на div, който искате да центрирате. И не съм казал, че OP трябва да използва % в margin-top. - person tuff; 14.09.2012
comment
Не съм съгласен с решението, тъй като ви заключва в предварително определена височина на елемента - но вашият коментар има смисъл. Може да искате да отразите това в отговора - person Oleg; 14.09.2012
comment
Добре, удебелих частта, която пропуснахте, надявам се, че сега е по-ясно. - person tuff; 14.09.2012
comment
@o.v.: Ако елементът няма фиксирана височина, можете просто да използвате JS, за да получите изчислената височина и след това да зададете съответно отрицателното горно поле. Това все още е най-добрият метод за вертикално центриране според мен. - person daGUY; 14.09.2012
comment
+1 - вече имаме div, който използваме като ограничителна кутия за img, която има зададена височина - person Izkata; 04.06.2013

Тези две решения изискват само два вложени елемента.
Първо - Относително и абсолютно позициониране ако съдържанието е статично (ръчно центриране).

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

или за течен дизайн - за точен център за съдържание използвайте примера по-долу:

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

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

Трябва да зададете „минимална височина“, в случай че съдържанието надвишава 50% от височината на прозореца. Можете също да манипулирате тази височина с медийна заявка за мобилни и таблетни устройства. Но само ако играете с отзивчив дизайн.

Предполагам, че можете да отидете по-далеч и да използвате прост JavaScript/JQuery скрипт, за да манипулирате минималната височина или фиксираната височина, ако има нужда по някаква причина.

Второ - ако съдържанието е течно можете също да използвате css свойства на таблица и клетка на таблица с вертикално подравняване и центрирано подравняване на текста:

/*in a wrapper*/  
display:table;   

и

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

Работи и мащабира перфектно, често се използва като адаптивно решение за уеб дизайн с мрежови оформления и медийни заявки, които манипулират ширината на обекта.

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

Предпочитам таблично решение за точно центриране на съдържанието, но в някои случаи относителното абсолютно позициониране ще свърши по-добра работа, особено ако не искаме да запазим точната пропорция на подравняването на съдържанието.

person DevWL    schedule 01.09.2015

Няма един лесен начин за центриране на div вертикално, който да свърши работа във всяка ситуация.

Има обаче много начини да го направите в зависимост от ситуацията.

Ето няколко от тях:

  • Задайте горна и долна подложка на родителския елемент, например padding:20px 0px 20px 0px
  • Използвайте таблица, клетката на таблицата центрира съдържанието си вертикално
  • Задайте относителната позиция на родителския елемент и div-ите, които искате да центрирате вертикално, на абсолютни и ги стилизирайте като top:50px; отдолу:50px; например

Можете също така да търсите в Google за "css вертикално центриране"

person hasu    schedule 13.09.2012

променлива височина, автоматичен марж отгоре и отдолу

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

променлива височина, автоматичен марж отгоре и отдолу

person user3668456    schedule 07.04.2017

Използване на 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 */
}

Вижте резултата

person DanielBlazquez    schedule 09.08.2016

Мисля, че можете да поправите това с Flexbox

.black {
  height : 200px;
  width : 200px;
  background-color : teal;
  border: 5px solid rgb(0, 53, 53);
  /* This is the important part */
  display : flex;
  justify-content: center;
  align-items: center;
}

.message {
  background-color :  rgb(119, 128, 0);
  border: 5px solid rgb(0, 53, 53);
  height : 50%;
  width : 50%;
  padding : 5px;
}
<div class="black">
    <div class="message">
        This is a popup message.
    </div>
</div>

person Younes Belaabda    schedule 06.10.2020

person    schedule
comment
Бихте ли споделили с нас какво представлява това решение? Освен това виждам изскачащото ви съобщение в долната част да не е центрирано - person Alex; 21.09.2017
comment
Пропуснах нещо, но сега е усъвършенствано, за да запази div в средата вертикално. можете да проверите сега. - person Seetpal singh; 25.09.2017