Абсолютна центрування по горизонталі і вертикалі в CSS

26

Від автора: Всі ми зустрічали margin: 0 auto; для виконання горизонтального центрування, але margin: auto; відмовлявся працювати для вертикального… досі! Насправді абсолютна центрування вимагає всього лише оголошеної висоти і цих стилів:

.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;.

Всередині контейнера

.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 для його вирівнювання усередині цього контейнера! Інші демо-приклади припускають, що ці стилі вже включені і забезпечують додані класи для реалізації різних властивостей.

Абсолютна центрування по горизонталі і вертикалі в CSS

Всередині області перегляду

.Absolute-Center.is-Fixed {
position: fixed;
z-index: 999;
}

Потрібно, щоб контентний блок центрировался у вікні перегляду? Встановіть його на position: fixed і призначте високий z-index, як у модального вікна на цій сторінці.

Mobile Safari: контентний блок буде центрований по вертикалі у всьому документі, не у вікні перегляду, якщо воно не знаходиться всередині контейнера position: relative.

Офсети

.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; для зсуву вліво.

Абсолютна центрування по горизонталі і вертикалі в CSS

Адаптивність

.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 не заперечує!

Абсолютна центрування по горизонталі і вертикалі в CSS

Переповнення

.Absolute-Center.is-Overflow {
overflow: auto;
}

Вміст, що височіє над блоком або контейнером (вікно перегляду або контейнер position: relative), буде переповнюватися і може вийти за межі тематичного блоку і контейнера, або навіть виявитися обрізаним. Просте додавання overflow: auto дозволить вмісту прокручуватися всередині блоку, поки контентний блок сам по собі не піднімається над своїм контейнером (можливо, з допомогою додавання max-height: 100%; якщо у вас до самого контентному блоку не встановлено відступів).

Абсолютна центрування по горизонталі і вертикалі в CSS

Зміна розміру

.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 викликає затримку, рівний часу переходу.

Абсолютна центрування по горизонталі і вертикалі в CSS

Зображення

HTML

Абсолютна центрування по горизонталі і вертикалі в CSS

CSS

.Absolute-Center.is-Image {
height: auto;
}
.Absolute-Center.is-Image img {
width: 100%;
height: auto;
}

Зображення теж працюють! Застосуйте до самого зображення клас/стиль і встановіть height: auto; як ви це зробили б із зображенням, розмір якого змінюється адаптивно, щоб той масштабировалось разом з контейнером. Зверніть увагу, що height: auto; працює для зображень, але змушує звичайний контентний блок розтягуватися для заповнення контейнера, якщо тільки ви не застосували метод змінної висоти. Ймовірно, це тому, що браузерам доводиться вважати висоту відображуваного зображення, тому margin: auto;у підсумку працює, як ніби ви заявили висоту у всіх тестованих браузерах.

Абсолютна центрування по горизонталі і вертикалі в CSS

Змінна висота

JavaScript

/* Тест 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

.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: Контентний блок центрується по вертикалі, але стає трохи не по центру по горизонталі при використанні ширини на основі відсотків.

Абсолютна центрування по горизонталі і вертикалі в CSS

Інші техніки

Absolute Centering – відмінне рішення проблеми центрування, але існують і інші методи, відповідні для окремих вимог. Найчастіше застосовуються або рекомендовані методи – негативні поля (Negative Margins), перетворення (Transforms), таблична осередок (Table Cell), вбудований блок (Inline-Block), а тепер ще Flexbox. Більш докладно вони розкриваються в інших статтях, тому тут я розповім саме основне.

Негативний margin (Negative Margins)

.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

Абсолютна центрування по горизонталі і вертикалі в CSS

Перетворення (Transforms)

.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

Іноді краї і текст у підсумку відображаються розмитими

Абсолютна центрування по горизонталі і вертикалі в CSS

Комірка таблиці (Table Cell)

HTML

CSS

.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;
}

Це взагалі, може бути, найкраща методика, просто тому, що висота варіюється разом з контентом, а браузерна підтримка просто відмінна. Головний недолік – зайва розмітка, вимагає у загальній складності трьох елементів для остаточного центрування.

ПЕРЕВАГИ:

Вміст змінної висоти

Контент переливається при розтягуванні батьківського елементу

Добре працює кроссбраузерно

ПОПЕРЕДЖЕННЯ:

Потрібна додаткова розмітка

Абсолютна центрування по горизонталі і вертикалі в CSS

Inline-Block

HTML

CSS

.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.25 em; /* Для офсету проміжків. Може змінюватись в залежності від шрифту */
}
.is-Inline .Center-Block {
max-width: 99%; /* Попереджає проблеми з довгим вмістом. Змушує контентний блок переміщатися догори */
/* max-width: calc(100% — 0.25 em) /* Тільки для IE9+ */
}

Користується великим попитом: центрування Inline-Block. Основна думка полягає в застосуванні display: inline-block, vertical-align: middle та псевдоэлемента для центрування тематичного блоку всередині контейнера. Його концепція найкраще пояснюється в статті CSS-Tricks Центрування в невідомості (Centering in the Unknown). У моєї реалізації є кілька нових прийомів, яких я ніде не бачив, і які допомагають розв’язати деякі проблеми.

Ширину тематичного блоку потрібно заявити не більше 100% контейнера мінус 0,25 em, якщо вміст ширше контейнера, як у блоку з довгим текстом, розбитих на параграфи. Інакше контентний блок буде зміщений вгору, що буде причиною використання :after. Застосування :before змушувало вміст зміщуватися вниз на 100%!

Якщо вашій контентному блоку потрібно зайняти якомога більше доступного горизонтального простору, можна додати max-width: 99%;, що працює для великих контейнерів, або max-width: calc(100% — 0.25 em) в залежності від підтримуваних вами браузерів і ширини контейнера.

Виграш майже той же, що в методиці Table Cell, але я спочатку відкинув цей спосіб із-за того, що багато в чому він є хаком. Тим не менш, його браузерна підтримка значна і він залишається популярною технікою.

ПЕРЕВАГИ:

Вміст змінної висоти

Контент переливається при розтягуванні батьківського елементу

Добре працює кроссбраузерно і може бути адаптований для підтримки IE7

ПОПЕРЕДЖЕННЯ:

Вимагає контейнера

Покладається на margin-left: -0.25 em; для правильного центрування по горизонталі, але може вимагати підгонки під різні шрифти/розміри

Ширину тематичного блоку потрібно заявляти не ширше 100% контейнера мінус 0,25 em.

Абсолютна центрування по горизонталі і вертикалі в CSS

Flexbox

.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

Для роботи в сучасних браузерах потрібно безліч вендорних префіксів з різним синтаксисом

Можливі проблеми продуктивності

Абсолютна центрування по горизонталі і вертикалі в CSS

Рекомендації

У кожній техніки свої переваги. Яку з них вибрати – в основному зводиться до питання про те, які браузери ви підтримуєте і як виглядає існуюча розмітка, а для вірного вибору потрібних характеристик користуйтеся порівняльною таблицею.

Absolute Centering відмінно працює як просте безпроблемне вступне рішення. Там, де ви до цього використовували Negative Margins, використовуйте замість нього Absolute Centering. Вам не доведеться мати справу з докучливою математикою для розрахунку полів або додаткової розміткою, і можна буде адаптивно міняти розмір блоків.

Якщо сайту потрібно вміст змінної висоти з найкращого браузерною сумісністю, спробуйте методику Table Cell або Inline-Block. Якщо ви дуже передовий розробник, дайте шанс Flexbox і пожните переваги його просунутих розміток.