Андрей Мотошин Front-end engineer

Центрирование в блоке с неизвестными размерами

#верстка, #перевод

Перевод статьи Криса Койера Centering in the Unknown.

Когда в верстке дело доходит до центрирования, то чем больше у вас информации о центрируемом элементе и о его родителе, тем легче. Так как же быть, если вы ничего о них не знаете? Даже не смотря на это, задачу можно решить.

Не особо сложно: известны размеры элемента

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

Допустим, вы знаете точную ширину и высоту элемента, который центрировали, но родительский элемент может изменить свои размеры.

Известны размеры элемента

Для абсолютного позиционирования элемента по центру вам нужно установить top и left равными 50%, а margin-top и margin-left приравнять к высоте и ширине разделенным на два и записанным со знаком минус. Получилась скороговорка, так что лучше прочитайте здесь.

Сложнее: неизвестны размеры элемента

Сложности начинаются, когда вы не знаете размеры центрируемого элемента.

Неизвестны размеры элемента

Самый простой способ центрирования в этом случае — таблицы:

<table style="width: 100%;">
  <tr>
    <td style="text-align: center; vertical-align: middle;">
      Неизвестный центрируемый элемент.
    </td>
  </tr>
</table>

Если вы заботитесь о семантике, то можете привести ее в соответствие с имеющимся содержимым.

<div class="something-semantic">
  <div class="something-else-semantic">
    Неизвестный центрируемый элемент.
  </div>
</div>

В этом случае получаете тот же результат, как и с помощью таблиц:

.something-semantic {
  display: table;
  width: 100%;
}
.something-else-semantic {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}

Возможно, вам пригодяться CSS-таблицы. Они отображаются немного иначе, чем обычные блочные div-элементы. Например, таблица при ширине 100% будет тянуться на столько, насколько это необходимо для ее содержимого, в то время как блочные элементы по умолчанию расширяются до размеров их родителя автоматически. Также могут возникнуть проблемы, если нужно позиционировать другой элемент внутри div или сделать что-то такое, что не применимо к ячейке таблицы.

Michal Czernow описал мне чрезвычайно интересную альтернативную технику, которая делает то же самое. Если мы создадим внутри родителя невидимый элемент, который занимает 100% высоты, а затем добавим vertical-align: middle этому и центрируемому элементу, то получим тот же результат.

Невидимый элемент

Так что получается, невидимый элемент не должен быть семантичным? Нет, он может быть псевдо-элементом.

/* Родитель может иметь любую ширину и высоту */
.block {
  text-align: center;
}

/* Невидимый элемент, сдвинутый для лучшего центрирования */
.block:before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
  margin-right: -0.25em; /* Сдвиг */
}

/* Центрируемый элемент
   может так же иметь любую ширину и высоту */
.centered {
  display: inline-block;
  vertical-align: middle;
  width: 300px;
}

Демо

Хочу вам сказать, что техника с невидимым элементом лучше, чем предыдущие и должна стать техникой центрирования на века. Но в реальности это почти то же самое, как и трюк с таблицами, который поддерживается всеми современными браузерами и IE 8+. Хоть IE 7 и не поддерживает псевдо-элементы, он так же не поддерживает и CSS-таблицы. Если нужна поддержка IE <= 7, значит пришло время для

(или использования несемантичного или чего-то другого для невидимого элемента).

Этот способ — не открытие. Gary Turner писал о нем 5 лет назад. Но я упомянул Michal’а за то, что он использовал псевдо-элементы и сделал этот метод самым семантически верным.