Как вертикально центрировать контент с переменной высотой внутри div?

158

Каков наилучший способ вертикального центрирования содержимого div, когда высота содержимого является переменной. В моем конкретном случае высота контейнера контейнера фиксирована, но было бы здорово, если бы было решение, которое работало бы в тех случаях, когда контейнер также имеет переменную высоту. Кроме того, я хотел бы, чтобы решение не использовало или очень мало использовало CSS-хаки и / или несемантическую разметку.

альтернативный текст

jessegavin
источник
метод в этой статье разваливается в Safari (4.0.5): S
7
@ ripper234 Не совсем так, поскольку этот вопрос касается div с переменной высотой
Rauli Rajande
9
Также этот вопрос был задан первым.
Ги Имамура

Ответы:

147

Просто добавь

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

к внутреннему div.

Он перемещает верхнюю границу внутреннего div на половину высоты внешнего div ( top: 50%;), а затем внутренний div на половину его высоты ( transform: translateY(-50%)). Это будет работать с position: absoluteили relative.

Имейте в виду, что transformи translateиметь префиксы поставщиков, которые не включены для простоты.

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

BlackCetha
источник
6
Просто интересно, почему это работает на Chrome и Firefox, но не на Safari. Тогда я заметил, что большинство transformсвязанных вещей имеют -webkit-префикс, и теперь это работает. Так же, как напоминание: не забудьте также добавить -webkit-префикс.
Михо
5
Используйте такой инструмент, как github.com/postcss/autoprefixer, чтобы обработать префиксы для вас.
Джейми Чонг
6
Этот ответ должен быть наверху.
Хосе Фаети
3
Это должно иметь гораздо больше голосов! Кстати, это тоже работает position: absolute, не так ли?
фее
4
Этот метод имеет неприятный побочный эффект в Chrome - если ваша обертка имеет нечетное количество пикселей, то translateбудет рендерить все размыто, поскольку она пытается обработать высоту .5px на всем.
Кит
157

Похоже, это лучшее решение, которое я нашел для этой проблемы, если ваш браузер поддерживает ::beforeпсевдоэлемент: CSS-хитрости: центрирование в неизвестном .

Не требует дополнительной разметки и, кажется, работает очень хорошо. Я не мог использовать display: tableметод, потому что tableэлементы не подчиняются max-heightсвойству.

.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
Теперь это решение BRILLIANT. Большое спасибо за размещение этого!
Трой Алфорд
Как и в случае с другим ответом, этот был бы намного лучше, если бы он описывал подход и включал код из ссылки.
KatieK
3
+1, это решение действительно довольно гениальное! Кстати, вы можете добавить .block { white-space: nowrap; font-size: 0; line-height: 0; }и оставить отрицательное правое поле для псевдоэлемента, вам просто нужно сбросить fs и lh на .centered ... вот так вы убедитесь, что элемент будет правильно расположен, даже если он шире, чем область просмотра (и не не нужно использовать IMO немного грязный отрицательный запас).
Саймон
@jessegavin - по вашему мнению ... как следующее складывается с подходом, который вы обрисовали: stackoverflow.com/questions/396145/…
pulkitsinghal
1
Кроме того, это ломается, когда внешний контейнер .block имеет минимальную высоту вместо высоты.
Линкольн Б
16

Это то, что мне нужно было сделать много раз, и последовательное решение все еще требует, чтобы вы добавили небольшую несемантическую разметку и некоторые браузерные хаки. Когда мы получим поддержку браузера для CSS 3, вы получите вертикальное центрирование без греха.

Для лучшего объяснения этой техники вы можете посмотреть статью, из которой я ее адаптировал , но в основном она включает добавление дополнительного элемента и применение различных стилей в IE и браузерах, которые поддерживают position:table\table-cellэлементы, не относящиеся к таблице.

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

Есть много способов (хаков) применять стили в определенных наборах браузеров. Я использовал условные комментарии, но посмотрите на статью, приведенную выше, чтобы увидеть два других метода.

Примечание. Существуют простые способы получить вертикальное центрирование, если вы заранее знаете некоторые высоты, если вы пытаетесь центрировать одну строку текста или в некоторых других случаях. Если у вас есть больше деталей, добавьте их, потому что может быть метод, который не требует взлома браузера или несемантической разметки.

Обновление: мы начинаем улучшать браузерную поддержку CSS3, предлагая как flex-box, так и transforms в качестве альтернативных методов для получения вертикального центрирования (среди прочих эффектов). Смотрите этот другой вопрос для получения дополнительной информации о современных методах, но имейте в виду, что поддержка браузеров все еще отрывочна для CSS3.

Prestaul
источник
Да, я нашел эту статью сегодня и не смог заставить ее работать для моей конкретной ситуации. Возможно, мне нужно изучить это дальше.
Джессегавин
Возможно, вы можете опубликовать код, который вы используете, который не работает?
Крис Марасти-Георг
Это все еще лучшее решение для этой проблемы?
ripper234
Эта статья, похоже, не работает на Chrome 23, Firefox 16 и IE 9. Этот ответ кажется лучшим решением.
Фернандо Коррейя
Нет, эта статья все еще работает в последних версиях Chrome и Firefox по состоянию на 24 февраля 2013 г.
OMA
9

Используя дочерний селектор, я взял невероятный ответ Фади выше и свел его к одному правилу CSS, которое я могу применить. Теперь все, что мне нужно сделать, это добавить contentCenteredимя класса к элементам, которые я хочу центрировать:

.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: http://codepen.io/dougli/pen/Eeysg

dougli
источник
Прохладно. Спасибо, что поделился. Следует обратить внимание на то, что *селектор будет работать хуже, чем принятый ответ. Не может быть проблемой, но стоит отметить. stevesouders.com/blog/2009/06/18/simplifying-css-selectors
jessegavin
Спасибо. Да, это, вероятно, будет работать хуже, но в настоящее время правила CSS, вероятно, не сильно влияют на вещи. Возможно, мы можем улучшить это, выбрав > divвместо этого. calendar.perfplanet.com/2011/…
dougli
Просто и замечательно. У меня работает отлично.
Ловро
4

Лучший результат для меня пока:

div для центрирования:

position: absolute;
top: 50%;
transform: translateY(-50%);
margin: 0 auto;
right: 0;
left: 0;
Лео Димуччо
источник
Работал как шарм
m4heshd
3

Вы можете использовать маржу авто. С flex, div, кажется, тоже центрирован вертикально.

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>
Лоик Г.
источник
дисплей: гибкость до сих пор практически экспериментальная функция; ни один браузер не
поддерживает
1

Для меня лучший способ сделать это:

.container{
  position: relative;
}

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

Преимущество не в том, чтобы явно указывать высоту

Леандро Кастро
источник
0

Это мое отличное решение для divдинамического (в процентах) роста.

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>  

Попробуйте сами.

user3432605
источник
0

Вы можете использовать гибкий дисплей, такой как код ниже:

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

Хассан Юсефи
источник