# Центрирование горизонтальное и вертикальное В CSS есть всего несколько техник центрирования элементов. Если их знать, то большинство задач решаются просто. [cut] ## Горизонтальное ### text-align Для центрирования инлайновых элементов -- достаточно поставить родителю `text-align: center`.: ```html
Текст
``` Для центрирования блока это уже не подойдёт, свойство просто не подействует. Например: ```html
Текст
``` Впрочем, в примере выше блок будет центрирован в IE6,7 (это отклонение от стандарта). ### margin: auto Для всех браузеров, кроме IE6,7, блок по горизонтали центрируется `margin: auto`.: ```html
Текст
``` В отличие от `width/height`, значение `auto` для `margin` само не появляется. Обычно `margin` равно конкретной величине для элемента, например `0` для `DIV`. Нужно поставить его явно. Значение `margin-left:auto/margin-right:auto` заставляет браузер выделять под `margin` всё доступное сбоку пространство. А если и то и другое `auto`, то слева и справа будет одинаковый отступ, таким образом элемент окажется в середине. Детали вычислений описаны в разделе спецификации [Calculating widths and margins](http://www.w3.org/TR/CSS21/visudet.html#Computing_widths_and_margins). ## Вертикальное Для горизонтального центрирования всё просто. Вертикальное же изначальное не было предусмотрено в спецификации CSS и по сей день вызывает ряд проблем. Есть три основных решения. ### position:absolute + margin Центрируемый элемент позиционируем абсолютно и опускаем до середины по вертикали при помощи `top:50%`: ```html
Текст
``` Это, конечно, не совсем центр. По центру находится верхняя граница. Нужно ещё приподнять элемент на половину своей высоты. **Высота центрируемого элемента должна быть известна.** Родитель может иметь любую высоту. Если мы знаем, что это ровно одна строка, то её высота равна `line-height`. **Приподнимем элемент на пол-высоты при помощи `margin-top`:** ```html
Текст
``` [smart header="Почему -0.625em?"] При стандартных настройках браузера высота строки `line-height: 1.25`, если поделить на два `1.25em / 2 = 0.625em`. Конечно, высота может быть и другой, главное чтобы мы её знали заранее. [/smart] Можно аналогично центрировать и по горизонтали, если известен горизонтальный размер, при помощи `left:50%` и отрицательного `margin-left`. ### Одна строка: line-height Вертикально отцентрировать одну строку в элементе с известной высотой `height` можно, указав эту высоту в свойстве `line-height`: ```html
Текст
``` Это работает, но лишь до тех пор, пока строка одна, а если содержимое вдруг переносится на другую строку, то начинает выглядеть довольно уродливо. ### Таблица с vertical-align У свойства [vertical-align](http://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align), которое управляет вертикальным расположением элемента, есть два режима работы. **В таблицах свойство `vertical-align` указывает расположение *содержимого* ячейки.** Его возможные значения:
`baseline`
Значение по умолчанию.
`middle`, `top`, `bottom`
Располагать содержимое посередине, вверху, внизу ячейки.
Например, ниже есть таблица со всеми 3-мя значениями: ```html *!* */!*
top middle bottom
``` Обратим внимание, что в ячейке с `vertical-align: middle` содержимое находится по центру. Таким образом, можно обернуть нужный элемент в таблицу размера `width:100%;height:100%` с одной ячейкой, у которой указать `vertical-align:middle`, и он будет отцентрирован. Но мы рассмотрим более красивый способ, который поддерживается во всех современных браузерах, и в IE8+. В них не обязательно делать таблицу, так как доступно значение `display:table-cell`. Для элемента с таким `display` используются те же алгоритмы вычисления ширины и центрирования, что и в `TD`. И, в том числе, работает `vertical-align`: Пример центрирования: ```html
``` **Этот способ замечателен тем, что он не требует знания высоты элементов.** Однако у него есть особенность. Вместе с `vertical-align` родительский блок получает табличный алгоритм вычисления ширины и начинает подстраиваться под содержимое. Это не всегда желательно. Чтобы его растянуть, нужно указать `width` явно, например: `300px`: ```html
``` Можно и в процентах, но в примере выше они не сработают, потому что структура таблицы "сломана" -- ячейка есть, а собственно таблицы-то нет. Это можно починить, завернув "псевдоячейку" в элемент с `display:table`, которому и поставим ширину: ```html
``` Если дополнительно нужно горизонтальное центрирование -- оно обеспечивается другими средствами, например `margin: 0 auto` для блочных элементов или `text-align:center` на родителе -- для других. ### Центрирование в строке с vertical-align Для инлайновых элементов (`display:inline/inline-block`), включая картинки, свойство `vertical-align` центрирует *сам инлайн-элемент в окружающем его тексте*. В этом случае набор значений несколько другой: [iframe src="vertical-align" height="300" link edit border="1"] Это можно использовать и для центрирования, если высота родителя известна, а центрируемого элемента -- нет. Допустим, высота внешнего элемента `120px`. Укажем её в свойстве `line-height`: ```html
Центрирован
вертикально
``` Работает во всех браузерах и IE8+. Свойство `line-height` наследуется, поэтому надо знать "правильную" высоту строки и переопределять её для `inner`. ### Центрирование с vertical-align без таблиц Если центрирование должно работать для любой высоты родителя и центрируемого элемента, то обычно используют таблицы или `display:table-cell` с `vertical-align`. Если центрируются не-блочные элементы, например `inline` или `inline-block`, то `vertical-align` может решить задачу без всяких таблиц. Правда, понадобится вспомогательный элемент (можно через `:before`). Пример: ```html
Центрированный
Элемент
``` Для всех современных браузеров и IE8 можно добавить вспомогательный элемент через `:before`: ```html
Центрированный
Элемент
``` В пример выше добавлено также горизонтальное центрирование `text-align: center`. Но вы можете видеть, что на самом деле внутренний элемент не центрирован горизонтально, он немного сдвинут вправо. Это происходит потому, что центрируется *весь текст*, а перед `inner` находится пробел, который занимает место. Варианта два:
  1. Убрать лишний пробел между `div` и началом `inner`, будет `
    ...`.
  2. Оставить пробел, но сделать отрицательный `margin-left` у `inner`, равный размеру пробела, чтобы `inner` сместился левее.
Второе решение: ```html
Центрированный
Элемент
``` ## Итого Обобщим решения, которые обсуждались в этой статье. Для горизонтального центрирования: Для вертикального центрирования одного блока внутри другого:
Если размер центрируемого элемента известен, а родителя - нет
Родителю `position:relative`, потомку `position:absolute; top:50%` и `margin-top:-<половина-высоты-потомка>`. Аналогично можно отцентрировать и по горизонтали.
Если нужно отцентрировать одну строку в блоке, высота которого известна
Поставить блоку `line-height: <высота>`. Нужны конкретные единицы высоты (`px`,`em`...). Значение `line-height:100%` не будет работать, т.к. проценты берутся не от высоты блока, а от текущей `line-height`.
Высота родителя известна, а центрируемого элемента - нет.
Поставить `line-height` родителю во всю его высоту, а потомку поставить `display:inline-block`.
Высота обоих элементов неизвестна.
Два варианта:
  1. Сделать элемент-родитель ячейкой таблицы при помощи `display:table-cell`(IE8) или реальной таблицы, и поставить ему `vertical-align:middle`. Отлично работает, но мы имеем дело с таблицей вместо обычного блока.
  2. Решение с вспомогательным элементом `outer:before` и инлайн-блоками. Вполне универсально и не создаёт таблицу.