Як відцентрувати елемент у CSS: Flexbox, Grid, Margin та Position

Привіт:) Центрування елементів у CSS — це одна з найчастіших задач, з якою щодня стикається верстальник та фронтенд-розробник. Незважаючи на появу сучасних специфікацій, вибір правильного підходу досі залежить від типу елемента (інлайновий чи блоковий), типу контексту (Flexbox, Grid, Absolute) та необхідності центрування по одній чи двох осях.

У цьому гайді детально розберу всі актуальні методи горизонтального та вертикального центрування: від класичних margin: auto до лаконічних place-items: center.

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

Рядкові (інлайнові) елементи

Для центрування тексту (<span>, <a>, <strong>) чи елементів inline-block достатньо задати батьківському контейнеру властивість text-align: center.

Важливо: Властивість застосовується саме до батьківського контейнера, а не до самого інлайн-елемента.

.wrapper {
  width: 500px;
  height: 150px;
  padding: 5px;

  outline: 1px solid red;
}

.centering {
  text-align: center;

  outline: 1px solid blue;
}
<div class="wrapper">
  <h1 class="centering">Text</h1>
  <p class="centering">Text</p>
  <div class="centering">Text</div>
</div>

Блокові елементи

У цьому випадку властивість text-align не працюватиме. Для коректного вирівнювання використовують margin. Властивість можна вказати 3-ма варіантами:

/* ВАРІАНТ 1 */

margin: auto;

/* ВАРІАНТ 2 */

margin: 0 auto;

/* ВАРІАНТ 3 */

margin-left: auto;
margin-right: auto;

Кінцевий код:

.wrapper {
  width: 500px;
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}

.centering {
  width: 100px;
  margin: 0 auto;

  outline: 1px solid blue;
}
<div class="wrapper">
  <div class="centering">Text</div>
</div>

Значення auto властивості margin, на відміну від width та height, самостійно не з'являється. Зазвичай margin рівна конкретній величині елемента, наприклад 0 для div. Потрібно встановити її явно.

Значення margin-left: auto та margin-right: auto змушують браузер виділяти під margin весь доступний збоку простір. А якщо й те, й інше рівне auto, то ліворуч і праворуч буде однаковий відступ. А тому елемент опиниться в середині.

Детальніше із роботою обчислень відступів можете ознайомитися в оф. специфікації.

Зображення

Також цей метод підходить для горизонтального центрування зображень. Так як <img> є рядковим (інлайновим) тегом, то важливо його зробити блоковим:

.wrapper {
  width: 500px;
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}

.centering {
  display: block;
  margin: 0 auto;

  outline: 1px solid blue;
}
<div class="wrapper">
  <img class="centering" src="https://placehold.co/100x50.png" alt="Image">
</div>

Абсолютно позиціонований елемент

Ще один випадок, коли елемент позиціонується абсолютно. У такому разі важливо визначити, відносно якого саме батьківського елементу. Останньому потрібно присвоїти position: relative. Точно визначену ширину батьківському елементу (у прикладі це <div> із класом wrapper) вказувати не обов'язково.

.wrapper {
  position: relative;
  width: 500px; /* ширина не обов'язкова */
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}
	
.centering {
  position: absolute;
  left: 50%;
  transform: translateX(-50%); /* або transform: translate(-50%, 0); */

  outline: 1px solid blue;
}
<div class="wrapper">
  <div class="centering">Текст</div>
</div>

Flex-елементи

Цей спосіб передбачає використання flex-контейнера, всередині якого й будуть центруватися елементи, незалежно від їх типу (рядкові чи блокові).

У коді нижче я створив 2 однакових div-контейнери з класом wrapper. Для прикладу в одному помістив блоковий елемент, а в іншому — рядковий (інлайновий).

.wrapper {
  display: flex;
  justify-content: center;

  width: 500px;
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}

.centering {
  outline: 1px solid blue;
}
<div class="wrapper">
  <div class="centering">Текст</div>
</div>
<div class="wrapper">
  <p class="centering">Абзац</p>
</div>

Вертикальне центрування

Вертикальне вирівнювання по центру початково не було визначене у специфікації CSS. Але із зростом складності макетів використовується постійно.

Розгляну різні випадки.

Один рядок тексту (через line-height)

Нехай є елемент (рядковий або блоковий: <p>, <span> або <div>), у якому всього лише один рядок, а його контейнер має визначену висоту. У такому випадку достатньо цьому елементові задати властивість line-height із значенням, рівним висоті контейнера. Властивість спрацює як для контейнера, так і для елемента із одним рядком.

Вваріант 1

.wrapper {
  width: 500px;
  height: 100px;
  padding: 5px;

  line-height: 100px;

  outline: 1px solid red;
}
	
.centering {
  outline: 1px solid blue;
}
<div class="wrapper">
  <!-- Тут може бути блоковий або інлайновий елемент -->
  <span class="centering">Абзац</span>
</div>

Вваріант 2

p {
  margin: 0px;
  padding: 0px;
}

.wrapper {
  width: 500px;
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}
	
.centering {
  line-height: 100px;
			
  outline: 1px solid blue;
}
<div class="wrapper">
  <!-- Тут може бути блоковий або інлайновий елемент -->
  <p class="centering">Абзац</p>
</div>

Абсолютно позиціонований елемент

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

.wrapper {
  position: relative;

  width: 500px;
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}

.centering {
  position: absolute;
	
  top: 50%;
  transform: translateY(-50%); /* або transform: translate(0, -50%); */

  outline: 1px solid blue;
}
<div class="wrapper">
  <span class="centering">Абзац</span>
</div>

Властивість vertical-align

Спеціально для таблиць є окрема властивість vertical-align, яка керує вертикальним розташуванням елемента в комірці. Також її можна використати й для інших HTML-тегів.

Для таблиці код буде наступним:

table {  
  border-collapse: collapse; 
}

td {
  height: 100px;
  border: 1px solid blue;
}
<table>
  <tr>
    <td style="vertical-align: top">Зверху</td>
	<td style="vertical-align: middle">У центрі</td>
	<td style="vertical-align: bottom">Знизу</td>
  </tr>
</table>

У комірці таблиці з vertical-align: middle вміст знаходиться по центру. А тому можна обернути потрібний елемент в таблицю розміру width: 100%;

У випадку будь-якого іншого тегу (не <table>):

.wrapper {
  display: table-cell; 
  vertical-align: middle;

  width: 500px;
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}

.centering {
  outline: 1px solid blue;
}
<div class="wrapper">
  <h2 class="centering">Заголовок H2</h2>
</div>

Цей спосіб крутий тим, що не вимагає явного вказання висоти елементів. Однак він має особливість. Разом з vertical-align батьківський блок отримує табличний алгоритм обчислення ширини і починає підлаштовуватись під вміст. А це не завжди бажано. Щоб його розтягнути, потрібно для батьківського блоку явно вказати width.

Flex-елементи

Тут все просто:

.wrapper {
  display: flex;
  align-items: center;

  width: 500px;
  height: 100px;
  padding: 5px;

  outline: 1px solid red;
}
	
.centering {
  outline: 1px solid blue;
}
<div class="wrapper">
  <span class="centering">Текст</span>
</div>

Повне центрування по 2 осях

CSS Grid (place-items: center)

Найсучасніший та найкоротший спосіб повністю відцентрувати вміст у блоці за допомогою CSS Grid.

.grid-container {
  display: grid;
  place-items: center;

  min-height: 200px;
}

Flexbox (margin: auto у дочірнього елемента)

Маловідомий, але дуже зручний трюк: якщо задати батькові display: flex, то дочірній елемент з margin: auto автоматично відцентрується по обох осях без додавання justify-content чи align-items.

Головна перевага: не потрібно знати точні фіксовані розміри (width та height) дочірнього елемента.

.flex-container {
  display: flex;
  min-height: 200px;
}
.flex-child {
  margin: auto; /* Центрує по горизонталі та вертикалі */
}

Абсолютне центрування через transform

Це найуніверсальніший та найпопулярніший класичний метод, коли потрібно відцентрувати елемент (наприклад, модальне вікно, вспливаючий банер або іконку) рівно по центру батьківського блоку по обох осях.

.parent {
  position: relative;
  min-height: 300px;
  background-color: #f4f4f4;
}

.child-centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
<div class="parent">
  <div class="child-centered">
    Елемент відцентровано по обох осях
  </div>
</div>

Абсолютне центрування через top/bottom/left/right: 0 та margin: auto

Альтернативний метод для абсолютно позиціонованого елемента з фіксованими розмірами без використання transform.

.parent {
  position: relative;
  height: 300px;
}
.child-fixed {
  position: absolute;
  width: 200px;
  height: 100px;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
}

Михайло Петров
Михайло Петров

Мене звати Михайло. Я — WordPress-розробник. Створюю візитки, корпоративні сайти, інтернет-магазини, блоги на WordPress. Надаю консультації з WordPress.