Мастер-классы по Javascript Екатеринбург Ростов-на-Дону Москва Узнать больше...
Содержание (скрыть) Содержание (показать)

Техники центрирования

  1. Горизонтальное
    1. text-align
    2. margin: auto
  2. Вертикальное
    1. position:absolute + margin
  3. Одна строка: line-height
  4. vertical-align
    1. Таблица
    2. В строке
  5. Центрирование с vertical-align без таблиц
  6. Итого

В CSS есть всего несколько техник центрирования элементов. Если их знать, то большинство задач решаются просто.

Горизонтальное

text-align

Для центрирования инлайновых элементов — достаточно поставить родителю text-align: center:

<style>
  .outer {
    *!*text-align: center;*/!*
    border: 1px solid blue;
  }
</style>

<div class="outer">Текст</div>

Для центрирования блока это уже не подойдёт, свойство просто не подействует. Например:

<style>
  .outer {
    *!*text-align: center;*/!*
    border: 1px solid blue;
  }
  .inner {
    width: 100px;
    border: 1px solid green;
  }
</style>

<div class="outer">
  <div class="inner">Текст</div>
</div>

Впрочем, в примере выше блок будет центрирован в IE6,7 (это отклонение от стандарта).

margin: auto

Для всех браузеров, кроме IE6,7, блок по горизонтали центрируется margin: auto:

<style>
  .outer {
    *!*text-align: center;*/!* /* Для IE<8 */
    border: 1px solid blue;
  }
  .inner {
    width: 100px;
    border: 1px solid green;
    *!*margin: auto;*/!* /* Для IE8+ и других браузеров */
  }
</style>

<div class="outer">
  <div class="inner">Текст</div>
</div>

В отличие от width/height, значение auto для margin само не появляется. Обычно margin равно конкретной величине для элемента, например 0 для DIV. Нужно поставить его явно.

Значение margin-left:auto/margin-right:auto заставляет браузер выделять под margin всё доступное сбоку пространство. А если и то и другое auto, то слева и справа будет одинаковый отступ, таким образом элемент окажется в середине. Детали вычислений описаны в разделе спецификации Calculating widths and margins.

Вертикальное

Для горизонтального центрирования всё просто. Вертикальное же изначальное не было предусмотрено в спецификации CSS и по сей день вызывает ряд проблем.

Есть три основных решения.

position:absolute + margin

Центрируемый элемент позиционируем абсолютно и поднимаем по вертикали при помощи top:50%:

<style>
  .outer {
    position: relative;
    height: 5em;
    border: 1px solid blue;
  }

  .inner {
*!*
    position: absolute;
    top: 50%;
*/!*
    border: 1px solid green;
  }
</style>

<div class="outer">
  <div class="inner">Текст</div>
</div>

Это, конечно, не совсем центр. По центру находится верхняя граница. Нужно ещё приподнять элемент на половину своей высоты.

Высота центрируемого элемента должна быть известна. Родитель может иметь любую высоту.

Если мы знаем, что это ровно одна строка, то её высота равна line-height.

Приподнимем элемент на пол-высоты при помощи margin-top:

<style>
  .outer {
    position: relative;
    height: 5em;
    border: 1px solid blue;
  }

  .inner {
    position: absolute;
    top: 50%;
*!*
    margin-top: -0.675em;
*/!*
    border: 1px solid green;
  }
</style>

<div class="outer">
  <div class="inner">Текст</div>
</div>

Почему -0.675em?

При стандартных настройках браузера высота строки line-height: 1.25, если поделить на два 1.25em / 2 = 0.675em.

Конечно, высота может быть и другой, главное чтобы мы её знали заранее.

Можно аналогично центрировать и по горизонтали, если известен горизонтальный размер, при помощи left:50% и отрицательного margin-left.

Одна строка: line-height

Вертикально отцентрировать одну строку в элементе с известной высотой height можно, указав эту высоту в свойстве line-height:

<style>
  .outer {
    height: 5em;
*!*
    line-height: 5em;
*/!*
    border: 1px solid blue;
  }
</style>

<div class="outer">
  Текст
</div>

Чтобы было лучше видно строку, добавим вокруг неё SPAN с зелёной рамочкой:

<style>
  .outer {
    height: 5em;
*!*
    line-height: 5em;
*/!*
    border: 1px solid blue;
  }
</style>

<div class="outer">
  <span style="border:1px solid green">Текст</span>
</div>

Это работает, но лишь до тех пор, пока строка одна.

vertical-align

У свойства vertical-align, которое управляет вертикальным расположением элемента, есть два режима работы.

Таблица

В таблицах vertical-align, которое центрирует содержимое ячейки.

Возможные значения:

baseline
Значение по умолчанию.
middle, top, bottom
Распологать содержимое посередине, вверху, внизу ячейки.

Например:

<style>
  table { 
    border-collapse: collapse;
  }

  td {    
    border: 1px solid black;
    height: 100px;
  }
</style>

<table>
<tr>
*!*
  <td style="vertical-align: top">top</td>
  <td style="vertical-align: middle">middle</td>
  <td style="vertical-align: bottom">bottom</td>
*/!*
</tr>
</table>

Во всех браузерах, кроме IE<8, доступно значение display:table-cell. Для элемента с таким display используются те же алгоритмы вычисления ширины и центрирования, что и в TD. А также, работает vertical-align:

<div style="*!*display: table-cell; vertical-align: middle; */!* height: 100px; border: 1px solid black">
  По центру
</div>

Этот способ замечателен тем, что он не требует знания высоты элементов.

Однако у него есть особенность. Вместе с vertical-align блок получает табличный алгоритм вычисления ширины и начинает подстраиваться под содержимое.

Чтобы его растянуть, нужно указать width явно, но не в процентах — проценты в этом случае не сработают, а в конкретных единицах измерения.

<div style="display: table-cell; vertical-align: middle; height: 100px; *!*width: 300px*/!*; border: 1px solid black">
  Ячейка шириной 300px
</div>

Проценты же не работают потому, что структура таблицы «сломана» — ячейка есть, а собственно таблицы-то нет.

Это можно починить, завернув «псевдоячейку» в элемент с display:table, которому и поставим ширину:

<div style="*!*display: table; width: 100%*/!*">
<div style="display: table-cell; vertical-align: middle; height: 100px; border: 1px solid black">
  Растянут по ширине, центрирован вертикально.
</div>
</div>

В строке

Для инлайновых элементов (display:inline/inline-block), включая картинки, свойство vertical-align центрирует сам инлайн-элемент в окружающем его тексте.

В этом случае набор значений несколько другой:
Открыть в новом окне Открыть в песочнице

Это можно использовать и для центрирования, если высота родителя известна, а центрируемого элемента — нет.

Допустим, высота внешнего элемента 120px. Укажем её в свойстве line-height:

<style>
  .outer {
    line-height: 120px;
  }
  .inner {
    display: inline-block; /* центрировать..*/
    vertical-align: middle;  /* ..по вертикали */
    line-height: 1.25; /* переопределить высоту строки на обычную */
    border: 1px solid red;
  }
</style>
<div class="outer" style="height: 120px;border: 1px solid blue">
  <span class="inner">Центрирован<br>вертикально</span>
</div>

Работает во всех браузерах и IE8+.

Свойство line-height наследуется, поэтому надо знать «правильную» высоту строки и переопределять её для inner.

Центрирование с vertical-align без таблиц

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

Можно сделать аналогичную вещь без таблиц, при помощи inline-block, vertical-align и вспомогательного элемента:

<style>
.before {
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

.inner {
  display: inline-block;
  vertical-align: middle;
}
</style>

<div class="outer" style="height:100px;border:1px solid black">
  <span class="before"></span>
  <span class="inner" style="border:1px solid red">
    Центрированный<br>Элемент
  </span>
</div>

  • Перед центрируемым элементом помещается вспомогательный инлайн-блок before, занимающий всю возможную высоту.
  • Центрируемый блок выровнен по его середине.

Для всех современных браузеров и IE8 можно добавить вспомогательный элемент через :before:

<style>
*!*.outer:before*/!* {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

.inner {
  display: inline-block;
  vertical-align: middle;
}

/* добавим горизонтальное центрирование */
.outer {
  text-align: center;
}
</style>

<div class="outer" style="height:100px; width: 140px; border:1px solid black">
  <span class="inner" style="border:1px solid red">
    Центрированный<br>Элемент
  </span>
</div>

В пример выше добавлено также горизонтальное центрирование text-align: center. Но вы можете видеть, что на самом деле внутренний элемент не центрирован горизонтально, он немного сдвинут вправо.

Это происходит потому, что центрируется весь текст, а перед inner находится пробел, который занимает место.

Варианта два:

  1. Убрать лишний пробел между div и началом inner, будет <div class="outer"><span class="inner">....
  2. Оставить пробел, но сделать отрицательный margin-left у inner, равный размеру пробела, чтобы inner сместился левее.

Второе решение:

<style>
.outer:before {
  content: '';
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}

.inner {
  display: inline-block;
  vertical-align: middle;
*!*
  margin-left: -0.35em;
*/!*
}

.outer {
  text-align: center;
}
</style>

<div class="outer" style="height:100px; width: 140px; border:1px solid black">
  <span class="inner" style="border:1px solid red">
    Центрированный<br>Элемент
  </span>
</div>

Итого

Обобщим решения, которые обсуждались в этой статье.

Для горизонтального центрирования:

  • text-align: center — центрирует инлайн-элементы в блоке. В IE<8 центрирует всё, но это нестандартное поведение.
  • margin: 0 auto — центрирует блок внутри родителя. У блока должна быть указана ширина.

Для вертикального центрирования одного блока внутри другого:

Если размер центрируемого элемента известен, а родителя - нет
Родителю 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 и инлайн-блоками. Вполне универсально и не создаёт таблицу.

Поместите мяч в центр поля при помощи CSS.

Исходный код:

Используйте CSS, чтобы поместить мяч в центр:

  • CSS для центрирования может использовать размеры мяча.
  • CSS для центрирования не должен опираться на конкретный размер поля.

Исходный документ: tutorial/browser/dom/ball-source/index.html.

Решение
Решение

Сместим мяч в центр при помощи left/top=50%, а затем приподымем его указанием margin:

#ball {
  position: absolute;
  left: 50%;
  top: 50%;
  margin-left: -20px;
  margin-top: -20px;
}

Полный код решения: tutorial/browser/dom/ball-css/index.html

Создайте при помощи HTML/CSS форму для логина в модальном окне.

Открыть в новом окне

Требования:

  • Кнопки окна вне формы не работают (даже на левый край нажать нельзя).
  • Полупрозрачный голубой «экран» остстоит от границ на 20px.
  • Форма центрирована вертикально и горизонтально, её размеры фиксированы.
  • Посетитель может менять размер окна браузера, геометрия должна сохраняться.
  • Не ломается при прокрутке.

Браузеры: все основные, IE8+.

Исходный документ: tutorial/browser/css/modal-login-src/index.html.

Структура решения
Решение
Структура решения

Шаги решения:

  1. Для того, чтобы элементы окна не работали, их нужно перекрыть DIV'ом с большим z-index.
  2. Внутри него будет лежать «экран» с полупрозрачностью. Чтобы он растягивался, можно дать ему position: absolute и указать все координаты top/left/right/bottom. Это работает в IE8+.
  3. Форму можно отцентрировать при помощи margin или display: table-cell + vertical-alignment на внешнем DIV.
Решение

Почему вертикальное центрирование в этом коде не работает?

Нажмите на просмотр, чтобы увидеть.

<style>
  .arrow {
    position: absolute;
    height: 60px;
    border: 1px solid black;
    font-size: 28px;

*!*
    display: table-cell;
    vertical-align: middle;
*/!*
  }
</style>

<div class="arrow">«</div>

Как починить центрирование (только CSS)? Все свойства CSS, кроме выделенных, менять нельзя.

Подсказка
Решение
Подсказка

Центрирование не работает из-за position: absolute.

Решение
Решение

Центрирование не работает потому, что position: absolute автоматически меняет элементу display на block.

В однострочном случае можно сделать центрирование при помощи line-height:

<style>
  .arrow {
    position: absolute;
    height: 60px;
    border: 1px solid black;
    font-size: 28px;

*!*
    line-height: 60px;
*/!*
  }
</style>

<div class="arrow">«</div>

Если же центрировать нужно несколько строк или блок, то есть и другие техники центрирования, которые сработают без display:table-cell.

См. также:

Комментарии

  1. Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  2. Если ваш комментарий касается задачи -- откройте её в отдельном окне и напишите там.
  3. Комментарии без смысла, с рекламой или не о статье вообще - удаляются.
Наверх

Содержание

Реклама

Нашли опечатку?

Нашли опечатку на сайте? Что-то кажется странным?
Выделите соответствующий текст и нажмите Ctrl+Enter!

Последние Комментарии

Помоги другим!

Помоги другим узнать о хорошей статье!