Центрирование элементов по вертикали на чистом CSS

  • CSS
  • 7,329
  • 0
  • 0
  • 0
  • 3 года назад

Оси в CSS

До сих пор в CSS было проблемой, что он работает преимущественно вдоль одной оси. В зависимости от контекста это может быть вертикальная или горизонтальная ось. И это отлично подходит для стека блочных элементов (расположенных один за другим), например:

~~~{.css} display: block; width: 100%;


Также легко отобразить элементы вдоль горизонтальной оси используя плавающие элементы (float). Однако если вы хотите сделать элементы динамически на обе оси, то у вас будет не так много вариантов для этого. В таком случае вам придётся использовать обходные пути или способы основанные на JavaScript. Но на данный момент новая спецификация CSS column (CSS столбцы) дает нам новую надежду на достижение этой цели используя только чистый CSS. Примечательно, что CSS столбцы отдают приоритет вертикальному выравниванию перед горизонтальным.

### Горизонтальное центрирование

Горизонтальное центрирование сделать очень просто. Существует несколько способов для достижения эффекта горизонтального центрирования элементов:

### Inline-block и Inline элементы с выравниванием текста

Inline-block и Inline элементы, обрабатываются как текст - они рассчитывают свои собственные значения ширины и не реагируют на заявленную ширину, если вы не объявили их как блочные элементы (см. Далее).

~~~{.css}
display: inline; /* [или] display: inline-block; */
text-align: center;

Inline-block и блочные элементы с полями

Элементы, которые объявлены как inline-block или block можно выровнять горизонтально по центру с помощью левого и правого полей (margin), которые рассчитываются автоматически:

~~~{.css} display: block; margin-left: auto; margin-right: auto;


### Нюансы с вертикальным центрированием

Выравнивание элементов по вертикали было достаточно сложной задачей. Было опубликовано много обходных путей - Chris Coyier (из CSS Triks) сделал удивительную подборку возможных хаков - так что я не буду здесь их подробно описывать.

Для примеров в этой статье используется следующая разметка:

~~~{.html}
<div class="box">
  <div>
    Содержимое, которое будет отцентрировано по вертикали
  </div>
</div>

Использование макета таблицы

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

~~~{.css} html, body { height: 100%; padding: 0px; margin: 0px; }

.box { display: table; width: 100%; }

.box > div { display: table-cell; text-align: center; vertical-align: middle; }


[http://jsfiddle.net/devacademy/zEGF9/1/](http://jsfiddle.net/devacademy/zEGF9/1/){:target="_blank"}

### Метод, основанный на JavaScript

Для людей, которые не являются поклонниками макета таблицы, могут использовать JavaScript. Для нашего примера я выбрал jQuery из-за его простоты использования, но сделать это с помощью чистого JS, конечно же, тоже возможно. Давайте сделаем базовые стили на CSS:

~~~{.css}
html, body {
    height: 100%;
    padding: 0px;
    margin: 0px;
}

.box {
    position: relative;
    width: 100%; 
    height: 100%;
}

.box > div {
    position: absolute;
    top: 50%;
    left: 50%;
}

Объявление размеров блока родителя обязательно, потому что абсолютно позиционируя дочерний элемент, мы вырываем его из потока документа, и поэтому родительский блок может свернуться (collapse).

Сейчас мы позиционируем внутренний div, таким образом, что ее верхняя левая точка будет в середине родителя, по горизонтали и вертикали. Однако так как дочерний элемент также имеет ненулевую ширину, он будет отображаться слишком далеко вниз и слишком далеко влево - поэтому такой способ делает центрирование не полным. Для того, чтобы компенсировать дочерний элемент, основанный на его содержимом, нам придется вычислить смещение, используя его собственные размеры с помощью JavaScript:

~~~{.javascript} $(function () { // Прослушиваем событие resize, чтобы пересчитать размеры блока $(window).resize(function () { $('.box > div').each(function () { $(this).css({ marginTop: $(this).outerHeight() -0.5, marginLeft: $(this).outerWidth() -0.5 }); }); }).resize(); // Вызываем resize когда DOM уже загрузился });


[http://jsfiddle.net/devacademy/T7YqB/2/](http://jsfiddle.net/devacademy/T7YqB/2/){:target="_blank"}

Однако недостатком этого метода на основе JS является то, что он неуклюже выглядит и не работает с посетителями, которые отключили JS (скорее всего, то уже не актуально, но тем не менее, я хотел бы этого избежать) и требует прослушивать события изменения размера окна для вычисления размеров элемента. Кроме того, браузеры вызывают **resize** событие слишком часто.

### Новый способ: CSS 2D transform

С появлением поддержки в браузерах **CSS 2D transform** (до 80% пользователей в мире), то теперь можно вертикально центрировать элементы без особых трудностей, хотя этот способ по-прежнему требует один дополнительный уровень вложенности.

Этот трюк CSS 2D transform очень прост — вместо вычисления в JavaScript, пусть движок браузера делает тяжелую работу:

~~~{.css}
.box {
    position: relative;
    width: 100%;
    height: 100%;
}

.box > div {
    position: absolute;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}

http://jsfiddle.net/devacademy/3BsR3/{:target="_blank"}

Если вы центрируете элементы с помощью CSS 2D transform, то пользователи, которые к сожалению застряли в старых обозревателях (причина этому: сами не хотят обновляться или не умеют или из-за ограничения компании в которой они работают) не будут обслуживаться. Для них ваш сайт будет выглядеть не совсем правильно. Но вы можете использовать резервный вариант — например, использовать Modernizr для обнаружения отсутствия CSS transform и использовать альтернативные методы для достижения того же эффекта на браузерах, которые не поддерживают эту технологию.

В целях поддержки WebKit пользователей, вам нужно будет использовать префикс конкретно для браузеров на этом движке, то есть -webkit-. Это немного странно, потому что версии Internet Explorer, а именно 10 и выше, поддерживает свойство transform без необходимости префикс -ms.

Кроме того можно поддержать идеи graceful degradation (отказоустойчивость клиентских веб-интерфейсов) и progressive enhancement (прогрессивное улучшение), которые позволяют пользователям использовать визуально несовершенный, но полностью функциональный сайт.

Комментарии

0