От автора: Все мы встречали margin: 0 auto; для выполнения горизонтального центрирования, но margin: auto; отказывался работать для вертикального… до сих пор! На самом деле абсолютное центрирование требует всего лишь объявленной высоты и этих стилей:
1 2 3 4 5 |
.Absolute-Center { margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; } |
Я – не первопроходец этого метода (хотя и осмелился назвать его Absolute Centering), и, может быть, это обычная техника, однако большая часть статей о вертикальном центрировании никогда о нем не упоминают и я нигде не видел его до тех пор, пока не порылся в разделе комментариев одной статьи.
В ней Саймон (Simon) связал с ним jsFiddle, чем отмел все прочие способы (тот же метод упоминался в комментариях Приитом (Priit)). При дальнейших исследованиях мне пришлось применять очень специфические ключевые слова, чтобы отыскать несколько других источников этого метода. Никогда до того не пользовавшийся данной техникой, я протестировал ее и обнаружил, насколько абсолютное центрирование потрясающе в самом деле.
ПРЕИМУЩЕСТВА:
Кроссбраузерность (включая IE8-10)
Не требуется специальной разметки, минимум стилей
Адаптивно работает с процентными соотношениями и min-/max-
Один класс для центрирования любого контента
Центрирование вне зависимости от отступа (без box-sizing!)
Блокам можно легко менять размер
Отлично работает с изображениями
ПРЕДУПРЕЖДЕНИЕ:
Нужно заявлять высоту
Рекомендуется установка overflow: auto для предотвращения переливания содержимого
Не работает в Windows Phone
БРАУЗЕРНАЯ СОВМЕСТИМОСТЬ:
Chrome, Firefox, Safari, Mobile Safari, IE8-10.
Метод абсолютного центрирования тестировался и безупречно работает в последних версиях Chrome, Firefox, Safari, Mobile Safari и даже IE8-10.
Пояснение
После изучения спецификаций и документации вот как я понимаю принцип работы Absolute Centering:
В нормальном потоке содержимого margin: auto; равен ’0′ для верха и низа. W3.org: Если ‘margin-top’ или ‘margin-bottom’ установлены на ‘auto’, их используемое значение равно 0.
position: absolute; выводит блок из обычного потока содержимого, отображая остальной контент так, как будто этого блока тут не было. Developer.mozilla.org: …абсолютно позиционированный элемент вынимается из потока и, таким образом, не занимает пространства
Установка top: 0; left: 0; bottom: 0; right: 0; задает браузеру новый ограничивающий прямоугольник для блока. На этом этапе блок заполнит все доступное пространство в своем офсетном родительском элементе, который является телом body или контейнером position: relative;. Developer.mozilla.org: Для абсолютно позиционированных элементов свойства top, right, bottom и left определяют офсеты от края содержащего блока элемента (относительно которого позиционирован элемент).
Назначение блоку width или height препятствует занятию блоком всего доступного пространства и заставляет браузер посчитать margin: auto на основе нового ограничивающего прямоугольника. Developer.mozilla.org: Поле [абсолютно позиционированного] элемента затем располагается внутри этих офсетов.
Так как блок позиционирован абсолютно и, следовательно, вне нормального потока, браузер назначает подходящие значения margin-top и margin-bottom, центрируя элемент в ранее определенных границах.
W3.org: Если ни одно из трех [top, bottom, height] не установлено на ‘auto’: если и ‘margin-top’, и ‘margin-bottom’ стоят на ‘auto’, решите уравнение с тем дополнительным ограничивающим условием, что два поля получают равные значения. Иначе говоря: отцентрируйте блок по вертикали
Похоже, Absolute Centering – это предназначенное применение margin: auto; согласно спецификации и, следовательно, должно работать во всех браузерах, подчиняющихся стандартам.
TL;DR: Абсолютно позиционированные элементы не отображаются в нормальном потоке, поэтому margin: auto; центрирует по вертикали внутри границ, установленных top: 0; left: 0; bottom: 0; right: 0;.
Внутри контейнера
1 2 3 4 5 6 7 8 9 10 11 12 |
.Center-Container { position: relative; } .Absolute-Center { width: 50%; height: 50%; overflow: auto; margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; } |
С помощью Absolute Centering можно разместить контентный блок внутри контейнера position: relative для его выравнивания внутри этого контейнера! Остальные демо-примеры предполагают, что эти стили уже включены и обеспечивают добавленные классы для реализации различных свойств.
Внутри области просмотра
1 2 3 4 |
.Absolute-Center.is-Fixed { position: fixed; z-index: 999; } |
Нужно, чтобы контентный блок центрировался в окне просмотра? Установите его на position: fixed и назначьте высокий z-index, как у модального окна на этой странице.
Mobile Safari: контентный блок будет центрирован по вертикали во всем документе, не в окне просмотра, если оно не находится внутри контейнера position: relative.
Офсеты
1 2 3 4 5 6 7 8 9 |
.Absolute-Center.is-Right { left: auto; right: 20px; text-align: right; } .Absolute-Center.is-Left { right: auto; left: 20px; text-align: left; } |
Если у вас фиксированный верхний колонтитул или нужно добавить другие офсеты, просто внесите в стили контентного блока что-то типа top: 70px;. Пока заявлен margin: auto;, контентный блок будет центрирован по вертикали в границах, заявленных вами с помощью top left bottom и right.
Также можно сдвинуть контентный блок вправо или влево, сохраняя при этом его вертикальное центрирование, с помощью right: 0; left: auto; для смещения вправо или left: 0; right: auto; для смещения влево.
Адаптивность
1 2 3 4 5 6 7 |
.Absolute-Center.is-Responsive { width: 60%; height: 60%; min-width: 200px; max-width: 400px; padding: 40px; } |
Возможно, самое большое преимущество Absolute Centering в том, что ширина/высота на основе процентов работают идеально! Даже стили min-width/max-width и min-height/max-height ведут себя так, как ожидается от более адаптивных блоков. Вперед, добавьте отступ элементу; Absolute Centering не возражает!
Переполнение
1 2 3 |
.Absolute-Center.is-Overflow { overflow: auto; } |
Содержимое, возвышающееся над блоком или контейнером (окно просмотра или контейнер position: relative), будет переполняться и может выйти за границы контентного блока и контейнера, или даже оказаться обрезанным. Простое добавление overflow: auto позволит содержимому прокручиваться внутри блока, пока контентный блок сам по себе не возвышается над своим контейнером (возможно, с помощью добавления max-height: 100%; если у вас к самому контентному блоку не установлено отступов).
Изменение размера
1 2 3 4 5 6 7 8 |
.Absolute-Center.is-Resizable { min-width: 20%; max-width: 80%; min-height: 20%; max-height: 80%; resize: both; overflow: auto; } |
Можно менять размер контентного блока с помощью других классов или Javascript’а, при этом пересчитывать центр вручную не требуется! Добавление свойства resize даже позволит самому пользователю менять размер блока с содержимым.
Absolute Centering поддерживает центрирование блока вне зависимости от того, как меняется его размер. Установка min-/max- ограничит размер блока до нужного вам и предотвратит его от переполнения окна/контейнера. Если вы не пользуетесь resize: both, то можете добавить transition для гладкой анимации изменения размеров. Обязательно установите overflow: auto, так как пользователи могут размер блока сделать меньше его содержимого. Absolute Centering является единственной протестированной техникой центрирования по вертикали, которая успешно поддерживает свойство resize: both.
ПРЕДУПРЕЖДЕНИЕ:
Установите max-width/max-height для уравнивания любого отступа самого контентного блока, иначе он переполнит свой контейнер.
Свойство resize не поддерживается в мобильных браузерах и IE 8-10, поэтому предусмотрите альтернативный способ изменения размера, если для впечатления пользователя это имеет существенное значение.
При попытке пользователя изменить размер сочетание свойств resize и transition вызывает задержку, равную времени перехода.
Изображения
HTML
1 |
<img src="//placekitten.com/g/500/200" class="Absolute-Center is-Image" alt="" /> |
CSS
1 2 3 4 5 6 7 8 |
.Absolute-Center.is-Image { height: auto; } .Absolute-Center.is-Image img { width: 100%; height: auto; } |
Изображения тоже работают! Примените к самому изображению класс/стиль и установите height: auto; как вы это сделали бы с изображением, размер которого меняется адаптивно, чтобы то масштабировалось вместе с контейнером. Обратите внимание, что height: auto; работает для изображений, но заставляет обычный контентный блок растягиваться для заполнения контейнера, если только вы не применили метод переменной высоты. Вероятно, это потому, что браузерам приходится считать высоту отображенного изображения, поэтому margin: auto;в итоге работает, как будто вы заявили высоту во всех тестируемых браузерах.
Переменная высота
JavaScript
1 2 3 4 |
/* Тест Modernizr’а контента переменной высоты */ Modernizr.testStyles('#modernizr { display: table; height: 50px; width: 50px; margin: auto; position: absolute; top: 0; left: 0; bottom: 0; right: 0; }', function(elem, rule) { Modernizr.addTest('absolutecentercontent', Math.round(window.innerHeight / 2 - 25) === elem.offsetTop); }); |
CSS
1 2 3 4 |
.absolutecentercontent .Absolute-Center.is-Variable { display: table; height: auto; } |
Absolute Centering на самом деле требуется заявленная высота, однако она может быть на процентной основе и контролироваться max-height. Из-за этого данный метод идеален для адаптивных сценариев, только убедитесь, что установили подходящее переполнение.
Одним из способов обхода заявленной высоты является добавление display: table, посредством чего контентный блок центрируется вне зависимости от длины содержимого. В некоторых браузерах это вызывает проблемы (в основном в IE и Firefox), поэтому мой приятель Кэлли (Kalley) из ELL Creative написал тест Modernizr’а для проверки поддержки браузером этого метода центрирования. Теперь можно делать прогрессивное улучшение
ПРЕДУПРЕЖДЕНИЕ:
Это грозит разрушением кроссбраузерной совместимости. Вам придется обдумать применение альтернативной техники, если окажется, что тест Modernizr’а не соответствует вашим ожиданиям.
Несовместимо с изменением размера.
Firefox/IE8: Применение display: table выравнивает контентный блок по верху, но он все равно центрируется по горизонтали.
IE9/10: Применение display: table выравнивает контентный блок по верху и левой стороне.
Mobile Safari: Контентный блок центрируется по вертикали, но становится слегка не по центру по горизонтали при использовании ширины на основе процентов.
Прочие техники
Absolute Centering – отличное решение проблемы центрирования, но существуют и другие методы, подходящие для отдельных требований. Чаще всего применяемые или рекомендуемые методы – отрицательные поля (Negative Margins), преобразования (Transforms), табличная ячейка (Table-Cell), встраиваемый блок (Inline-Block), а теперь еще Flexbox. Более подробно они раскрываются в других статьях, поэтому здесь я расскажу самое основное.
Отрицательный margin (Negative Margins)
1 2 3 4 5 6 7 8 9 |
.is-Negative { width: 300px; height: 200px; padding: 20px; position: absolute; top: 50%; left: 50%; margin-left: -170px; /* (ширина + отступ)/2 */ margin-top: -120px; /* (высота + отступ)/2 */ } |
Вероятно, самая привычная методика. Если знаете точные размеры, можно отцентрировать блок внутри контейнера путем установки отрицательного поля, равного половине ширины/высоты (плюс отступ, если не пользуетесь box-sizing: border-box) наряду с top: 50%; left: 50%;. Следует отметить, что это единственный из протестированных методов, который как следует работает в IE6-7.
ПРЕИМУЩЕСТВА:
Хорошо работает кроссбраузерно, включая IE6-7
Требует минимума кода
ПРЕДУПРЕЖДЕНИЕ:
Неадаптивен. Не работает с размерами на основе процентов и нельзя установить min-/max-
Содержимое может переполнять контейнер
Приходится компенсировать padding или применять box-sizing: border-box
Преобразования (Transforms)
1 2 3 4 5 6 7 8 9 |
.is-Transformed { width: 50%; margin: auto; position: absolute; top: 50%; left: 50%; -webkit-transform: translate(-50%,-50%); -ms-transform: translate(-50%,-50%); transform: translate(-50%,-50%); } |
Одна из простейших методик примерно с теми же преимуществами, что абсолютное центрирование, но поддерживает переменную высоту. Для центрирования назначьте контентному блоку transform: translate(-50%,-50%) с нужными вендорными префиксами и top: 50%; left: 50%;.
ПРЕИМУЩЕСТВА:
Содержимое переменной высоты
Требует минимума кода
ПРЕДУПРЕЖДЕНИЕ:
Не станет работать в IE8
Требует вендорных префиксов
Может мешать другим эффектам преобразования transform
Иногда края и текст в итоге отображаются размытыми
Ячейка таблицы (Table-Cell)
HTML
1 2 3 4 5 6 7 |
<div class="Center-Container is-Table"> <div class="Table-Cell"> <div class="Center-Block"> <!-- CONTENT --> </div> </div> </div> |
CSS
1 2 3 4 5 6 7 8 9 |
.Center-Container.is-Table { display: table; } .is-Table .Table-Cell { display: table-cell; vertical-align: middle; } .is-Table .Center-Block { width: 50%; margin: 0 auto; } |
Это вообще, может быть, самая лучшая методика, просто потому, что высота варьируется вместе с контентом, а браузерная поддержка просто отличная. Главный недостаток – лишняя разметка, требующая в общей сложности трех элементов для окончательного центрирования.
ПРЕИМУЩЕСТВА:
Содержимое переменной высоты
Контент переливается при растяжении родительского элемента
Хорошо работает кроссбраузерно
ПРЕДУПРЕЖДЕНИЕ:
Требуется дополнительная разметка
Inline-Block
HTML
1 2 3 4 5 |
<div class="Center-Container is-Inline"> <div class="Center-Block"> <!-- CONTENT --> </div> </div> |
CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
.Center-Container.is-Inline { text-align: center; overflow: auto; } .Center-Container.is-Inline:after, .is-Inline .Center-Block { display: inline-block; vertical-align: middle; } .Center-Container.is-Inline:after { content: ''; height: 100%; margin-left: -0.25em; /* Для офсета промежутков. Может варьироваться в зависимости от шрифта */ } .is-Inline .Center-Block { max-width: 99%; /* Предупреждает проблемы с длинным содержимым. Заставляет контентный блок перемещаться кверху */ /* max-width: calc(100% - 0.25em) /* Только для IE9+ */ } |
Пользуется большим спросом: центрирование Inline-Block. Основная мысль заключается в применении display: inline-block, vertical-align: middle и псевдоэлемента для центрирования контентного блока внутри контейнера. Его концепция лучше всего объясняется в статье CSS-Tricks Центрирование в неизвестности (Centering in the Unknown). У моей реализации есть несколько новых приемов, которых я нигде не видел, и которые помогают разрешить кое-какие проблемы.
Ширину контентного блока нужно заявить не более 100% контейнера минус 0,25em, если содержимое шире контейнера, как у блока с длинным текстом, разбитым на параграфы. Иначе контентный блок будет смещен вверх, что будет причиной использования :after. Применение :before заставляло содержимое смещаться вниз на 100%!
Если вашему контентному блоку требуется занять как можно больше доступного горизонтального пространства, можно добавить либо max-width: 99%;, что работает для больших контейнеров, либо max-width: calc(100% — 0.25em) в зависимости от поддерживаемых вами браузеров и ширины контейнера.
Выигрыш почти тот же, что в методике Table-Cell, но я изначально отбросил этот способ из-за того, что во многом он является хаком. Тем не менее, его браузерная поддержка значительна и он остается популярной техникой.
ПРЕИМУЩЕСТВА:
Содержимое переменной высоты
Контент переливается при растяжении родительского элемента
Хорошо работает кроссбраузерно и может быть адаптирован для поддержки IE7
ПРЕДУПРЕЖДЕНИЕ:
Требует контейнера
Полагается на margin-left: -0.25em; для правильного центрирования по горизонтали, но может потребовать подгонки под разные шрифты/размеры
Ширину контентного блока нужно заявлять не шире 100% контейнера минус 0,25em.
Flexbox
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
.Center-Container.is-Flexbox { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-align: center; -moz-box-align: center; -ms-flex-align: center; -webkit-align-items: center; align-items: center; -webkit-box-pack: center; -moz-box-pack: center; -ms-flex-pack: center; -webkit-justify-content: center; justify-content: center; } |
Будущее разметки CSS, Flexbox, является последней спецификацией CSS, созданной для решения обычных проблем разметки, таких как вертикальное центрирование. На Smashing Magazine уже опубликована великолепная статья о Центрировании элементов с помощью Flexbox (Centering Elements with Flexbox), которую стоит прочесть для получения более полного представления. Помните, что Flexbox – это не только способ центрирования, его можно применять для колонок и решения проблем разметки любых видов.
ПРЕИМУЩЕСТВА:
Содержимое может быть любой ширины и высоты, оно даже переполняется элегантно
Можно использовать для более продвинутых техник разметки.
ПРЕДУПРЕЖДЕНИЕ:
Отсутствует поддержка IE8-9
Требуется контейнер или стили для body
Для работы в современных браузерах требуется множество вендорных префиксов с разным синтаксисом
Возможны проблемы производительности
Рекомендации
У каждой техники свои преимущества. Какую из них выбрать – в основном сводится к вопросу о том, какие браузеры вы поддерживаете и как выглядит существующая разметка, а для верного выбора нужных характеристик пользуйтесь сравнительной таблицей.
Absolute Centering отлично работает как простое беспроблемное вводное решение. Там, где вы до этого использовали Negative Margins, используйте вместо него Absolute Centering. Вам не придется иметь дело с надоедливой математикой для расчета полей или дополнительной разметкой, и можно будет адаптивно менять размер блоков.
Если сайту требуется содержимое переменной высоты с наилучшей браузерной совместимостью, попробуйте методику Table-Cell или Inline-Block. Если вы очень передовой разработчик, дайте шанс Flexbox и пожните преимущества его продвинутых разметок.
Автор: Stephen Shaw
Источник: //coding.smashingmagazine.com/
Редакция: Команда webformyself.
Комментарии (6)