Как выровнять элемент по вертикали внутри блочного элемента

Постановка задачи: необходимо задать вертикальное выравнивание для inline или inline-block элементов внутри блочного элемента.

Подходы к решению задачи. Существуют различные способы, рассмотрим основные из них:

1. Представить блочный элемент как ячейку таблицы (display: table-cell).
2. IE6-7: метод expression.
3. Приравнивание межстрочного интервала (свойство line-height) и высоты блока (для однострочных элементов).
4. Позиционирование при помощи внешнего блока (position:absolute).

Ну а подведя итоги, рассмотрим еще один метод:

5. Выравнивание с помощью свойства vertical-align.

display: table-cell

Для вертикального выравнивания применяется свойство display: table-cell родительскому блоку, которое заставляет элемент эмулировать ячейку таблицы. Ему же задается высота и vertical-align: middle:

<!DOCTYPE html>
<html>
<head>
<title>Вертикальное выравнивание. Способ display: table-cell</title>
<style>
.wrapper {
   display:  table-cell;
   height:  100px;
   vertical-align:  middle;
}
</style>
</head>
<body>
   <div class="wrapper">
      Вертикально выравненная строка
   </div>
</body>
</html> 

Плюсы:

  • Простота;
  • Выравнивает как одну, так и несколько строк.

Минусы:

  • Не работает в IE7 и ниже;
  • Без дополнительных конструкций сложно манипулировать горизонтальным положением внешнего блока;
  • Не всем нравится сам факт использования display: table-cell.

IE6-7: метод expression

Т.к. предыдущий способ не работает в IE6-7, то надо исправить эту неприятность.

Expression - короткие куски JS кода, которые помещаются в файл стилей, выполняются один раз и работают только в IE. Expression невалидны. Добавляем к предыдущему примеру в файлы стилей для IE6 и 7 такой кусок кода:

.wrapper p {
   z-index:  expression(
      runtimeStyle.zIndex  = 1,
      this ==  ((200/2)-parseInt(offsetHeight)/2) &lt; 0
      ?  style.marginTop="0" :  style.marginTop=(200/2)-(parseInt(offsetHeight)/2) +'px'
   );
}

Рассматривать достоинства и недостатки смысла тут нет, т.к. достоинств нет, кроме того, что этот способ дополняет первый в IE6-7, но т.к. эти браузеры уже устарели, на них можно закрыть глаза.

line-height

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

<!DOCTYPE html>
<html>
<head>
<title>Вертикальное выравнивание. Способ line-height</title>
<style>
.wrapper {
   height:  100px;
   line-height:  100px;
}
</style>
</head>
<body>
   <div class="wrapper">
      Вертикально выравненная строка
   </div>
</body>
</html>

Плюсы:

  • Простота;
  • Кроссбраузерность.

Минусы:

  • Подходит только для однострочных элементов;
  • Позволяет выравнивать только по центру.

position и отрицательный margin вверх

Элемент можно выровнять по вертикали, задав ему фиксированную высоту и применив position: absolute и отрицательный margin-top, равный половине высоты выравниваемого элемента. Родительскому блоку должен быть присвоен position: relative:

<!DOCTYPE html>
<html>
<head>
<title>Вертикальное выравнивание. Способ line-height</title>
<style>
.wrapper {
   position:  relative;
   height:  400px;
}
.wrapper p {
   height:  200px;
   margin:  -100px 0 0;
   position:  absolute;
   top: 50%;
}
</style>
</head>
<body>
   <div class="wrapper">
      <p>Я выровнен по вертикали</p>
   </div>
</body>
</html>

Плюсы:

  • Кроссбраузерность;
  • Выравнивать элементы можно как по центру, так и в любом другом положении.

Минусы:

  • Трудоемко при большом количестве элементов;
  • Сложно управлять;
  • Необходимо знать и фиксировать высоту элемента;
  • В некоторых браузерах абсолютное позиционирование может вызвать снижение производительности.

Итог по популярным методам

Как видно, данные методы не являются универсальными – каждый из них имеет пусть и небольшие, но недостатки. Наиболее универсальным оказывается метод display: table-cell, но он мне никогда не нравился, к тому же мы очень долго не отказывались от поддержки IE6-7. Поэтому появилась необходимость поработать над чем-то более универсальным. Рассмотрим Выравнивание при помощи vertical-align.

Выравнивание при помощи vertical-align

Как известно, свойство vertical-align не работает для блочных элементов, поэтому применять это свойства для них бесполезно. Однако, данное свойство прекрасно работает для inline и inline-block элементов. Если мы попробуем применить данное свойство для элементов внутри блочного элемента, то мы получим следующую картину:

<!DOCTYPE html>
<html>
<head>
<title>Вертикальное выравнивание.  Способ vertical-align</title>
<style>
.wrapper
{
   width:600px;
   height:100px;
   padding:30px; /* Добавлено для наглядности  */
   margin:0 auto;
   background:#dfdfdf;
   font-family:Arial, Helvetica, sans-serif;
}
.el1 { vertical-align:middle; font-size:28px; }
.el2 { vertical-align:top; font-size:14px; }
.el3 { vertical-align:middle; font-size:18px; }
.el4 { vertical-align:middle; font-size:36px; }
.el5 { vertical-align:bottom; font-size:12px; }
</style>
</head>
<body>
   <div  class="wrapper">
      <span  class="el1">Элемент 1</span>
      <span class="el2">Элемент 2</span>
      <span class="el3">Элемент 3</span>
      <span class="el4">Элемент 4</span>
      <span class="el5">Элемент 5</span>
   </div>
</body>
</html>

Как видно, элементы выравниваются относительно строки, а не всего блока, что нам не подходит. Попробуем тогда внутрь блока добавить элемент (т.к. для inline элемента высоту задать нельзя, то элемент должен быть inline-block) с высотой равной высоте внешнего блока. Добавляем <span class="spanvmiddle"></span> (на картинке ниже показан серой линией) и получаем:

<!DOCTYPE html>
<html>
<head>
<title>Вертикальное выравнивание. Способ  vertical-align</title>
<style>
.wrapper
{
   width:600px;
   height:100px;
   padding:30px;  /* Добавлено для наглядности */
   margin:0 auto;
   background:#dfdfdf;
   font-family:Arial,  Helvetica, sans-serif;
}
.el1 { vertical-align:middle; font-size:28px; }
.el2 { vertical-align:top; font-size:14px; }
.el3 { vertical-align:middle; font-size:18px; }
.el4 { vertical-align:middle; font-size:36px; }
.el5 { vertical-align:bottom; font-size:12px; }
.spanvmiddle
{
   display:inline-block;
   height:100%;
   width:0px;
   overflow:hidden;
   vertical-align:middle;
   border-right:1px  solid #ccc;
}
</style>
</head>
<body>
   <div  class="wrapper">
      <span class="el1">Элемент 1</span>
      <span class="el2">Элемент 2</span>
      <span class="el3">Элемент 3</span>
      <span class="el4">Элемент 4</span>
      <span class="el5">Элемент 5</span>
      <span class="spanvmiddle"></span>
   </div>
</body>
</html> 

Зададим для всех элементов <span class="el*"></span> vertical-align:middle.

Что ж, одну строку мы таким образом отцентрировали. А что, если надо несколько строк? И тут проблем нет. Надо лишь для текстовых элементов задать display:inline-block:

<!DOCTYPE html>
<html>
<head>
<title>Вертикальное выравнивание. Способ  vertical-align</title>
<style>
.wrapper
{
   width:600px;
   height:100px;
   padding:30px;  /* Добавлено для наглядности */
   margin:0  auto;
   background:#dfdfdf;
   font-family:Arial,  Helvetica, sans-serif;
}
.wrapper span { display:inline-block; }
.el1 { vertical-align:middle; font-size:28px; }
.el2 { vertical-align:middle; font-size:11px; }
.el3 { vertical-align:middle; font-size:18px; }
.el4 { vertical-align:middle; font-size:32px; }
.el5 { vertical-align:middle; font-size:11px; }
.spanvmiddle
{
   display:inline-block;
   height:100%;
   width:0px;
   overflow:hidden;
   vertical-align:middle;
   border-right:1px solid #ccc;
}
</style>
</head>
<body>
   <div class="wrapper">
      <span class="el1">Элемент 1</span>
      <span class="el2">Элемент с двумя <br> строками текста</span>
      <span class="el3">Элемент 3</span>
      <span class="el4">Элемент 4</span>
      <span class="el5">Элемент <br> с тремя <br> строками текста</span>
      <span class="spanvmiddle"></span>
   </div>
</body>
</html>

Если нам не важна совместимость со старыми версиями IE, то элемент <span class="spanvmiddle"></span> мы можем удалить, а его стили заменить на:

.wrapper:after
{
content:"";
display:inline-block;
height:100%;
width:0px;
overflow:hidden;
vertical-align:middle;
}

Стоит отметить несколько моментов:

  • К элементам, которые выравниваются, нельзя применять свойство float.
  • Между соседними inline-block элементами всегда есть расстояние, поэтому если их надо прижать друг к другу, то для внешнего блока надо задать font-size:0px; а у самих элементов восстановить, задав нужное значение.
  • Для внутренних элементов таким образом можно задавать как одинаковые значения (top, bottom или middle), так и разные.

Плюсы:

  • Простота;
  • Кроссбраузерность;
  • Выравнивать элементы можно как по центру, так и в любом другом положении;
  • Подходит как для одной строки, так и для нескольких. Также, т.к. элемент имеет display:inline-block, он может содержать текст, графику (фон, картинка) и любой другой элемент.

Минусы:

  • Приходится добавлять дополнительный элемент;
  • При использовании псевдоэлемента :after, теряется поддержка старыми версиями IE.


Назад в раздел


С чего начинается продвижение сайта, старт работ по поисковому продвижению и раскрутке сайта в компании Пиксель Плюс
Начало работ по поисковому продвижению сайта в компании «Пиксель Плюс». Базовые понятия.
Необходимость ежемесячной оплаты работ по поисковому продвижению сайта. Основные работы по сайту для его эффективной раскрутки и себестоимость работ
Я бы хотел заплатить за продвижение своего сайта 1 раз и быть высоко в выдаче по конкурентным запросам всегда, возможно ли такое?
Продвижение по трафику: вопросы клиентов и ответы на них
Ряд вопросов по продвижению сайта по трафику. Нюансы тарификации, расчёта стоимости работ, абонентской оплаты.
Часто задаваемые вопросы по веб-аналитике (FAQ)
Вопросы, которые часто задаются заказчиками услуги по веб-аналитике и оказанию самой услуги. Что такое веб-аналитика? Зачем проекту нужна веб-аналитика? Зачем нужно определять KPI и какие они бывают? И так далее.
Время продвижения и внесения изменений в результаты продвижения сайта, скорость реагирования Яндекса (Yandex) на внесение изменений на сайте
Я оплатил услуги продвижения сайта на месяц. Прошло уже 10 дней и позиции в Яндексе не улучшились, вы там работаете или нет?
Эффективное поисковое продвижение сайта в Яндексе и Google, комплексное продвижение сайта во всех поисковиках
В каких поисковых системах (Яндекс, Гугл, Рамблер, Mail.ru) я получаю хорошие позиции если сотрудничаю с вашей компанией?