Grid vs Flexbox: що обрати?

9 хв. читання

Попри деякі спільні риси, CSS Grid та CSS Flexbox використовуються для дуже різних завдань; кожна з цих технологій вирішує свій набір проблем.

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

Grid базується на контейнерах, Flexbox – на вмісті

У макеті Flexbox розмір комірки (flex-елемент) визначається всередині, а у Grid розмір комірки (grid-елемент) визначається в grid-контейнері.

Збиває з пантелику?

Розглянемо приклад: HTML для створення рядку елементів.

<div class="row">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>

Додамо трохи стилів з Flexbox:

.row {
    margin: 20px auto;
    max-width: 300px;
    display: flex;
}
.row > div {
    border: 1px dashed gray;
    flex: 1 1 auto; /* Розмір елементів визначено всередині елементів */
    text-align: center;
    padding: 12px;
}

Ми визначили розмір комірок всередині flex-елементу встановивши flex: 1 1 auto;. Властивість flex є скороченням від flex-grow, flex-shrink та flex-basis. Значення за замовчуванням 0 1 auto. Зверніть увагу, що div row є flex-контейнером, тому ми не встановлюємо розмір елементів там. Ми встановлюємо розмір всередині flex-елемента.

При попередньому перегляді в браузері, побачимо рядок контейнерів, як і очікувалось:

Grid vs Flexbox: що обрати?

Тепер подивимось як отримати такий самий результат з Grid:

.row {
    margin: 20px auto;
    max-width: 300px;
    display: grid;
    grid-template-columns: 1fr 1fr 1fr 1fr; /* Розмір елементів визначається всередині контейнера */
}
.row div {
    border: 1px dashed gray;
    text-align: center;
    padding: 12px;
}

Наведений код працюватиме так само.

Тепер ми визначаємо розмір комірки, використовуючи grid-template-columns всередині grid-контейнера row, а не grid-елемента.

Зверніть увагу, що flexbox макет обчислюється після того, як вміст завантажено, тоді як макет grid обчислюється незалежно від вмісту. Тому, якщо можливо, уникайте використання flexbox для створення загального макета вашого сайту.

Grid має властивість gap, а Flexbox ні

Ви скажете, що Flexbox і Grid відрізняються тим, що в Grid ми можемо створювати прогалини між елементами з grid-column-gap :

Grid vs Flexbox: що обрати?

Для такого ж результату у Flexbox треба буде використовувати padding та вкладені контейнери або збільшити ширину flex-контейнера та використати властивість justify-content для розповсюдження flex-елементів.

Нам треба шукати альтернативу Flexbox, тому що він не має властивості gap. Однак, вона вже очікується. CSS Box Alignment Module 3 має CSS фічі, що стосуються вирівнювання контейнерів у всіх моделях макетів: block, table, flex та grid. Модуль Box Alignment поєднує властивості flexbox, grid та multi-column, які можуть використовуватись послідовно. У майбутньому ми зможемо додати прогалини з властивостями row-gap та column-gap.

Flexbox – одновимірний, Grid – двовимірний

Ми організовуємо елементи як рядки та колонки, тому що для макета використовувались таблиці. Flexbox та Grid базуються на цій концепції. Flexbox краще підходить для розміщення елементів в одному рядку або в одному стовпці. З Grid краще організовувати елементи в декількох рядках і стовпцях.

Іншими словами, Flexbox є одновимірним, а Grid – двовимірним. Розглянемо поширений варіант використання одновимірного макета — кнопки соціальних мереж.

Grid vs Flexbox: що обрати?

Всі елементи знаходяться в одному рядку. Ми можемо реалізувати це з Flexbox так:

<ul class="social-icons">
  <li><a href="#"><i class="fab fa-facebook-f"></i></a></li>
  <li><a href="#"><i class="fab fa-twitter"></i></a></li>
  <li><a href="#"><i class="fab fa-instagram"></i></a></li>
  <li><a href="#"><i class="fab fa-github"></i></a></li>
  <li><a href="#"><i class="fas fa-envelope"></i></a></li>
  <li><a href="#"><i class="fas fa-rss"></i></a></li>
</ul>

.social-icons {
  display: flex;
  list-style: none;
  justify-content: space-around;
}

Властивість justify-content визначає як розподілятиметься додатковий простір flex-контейнера між flex-елементами. Значення space-around розподіляє простір так, що flex-елементи розміщуються рівномірно, з однаковою кількістю простору навколо них.

Поглянемо на поширений приклад двовимірного макета:

Grid vs Flexbox: що обрати?

Ми не можемо реалізувати такий макет одним рядком чи колонкою — нам необхідно декілька рядків та колонок. Саме тому прийшов час CSS Grid.

<div class="container">
  <header>Header</header>
  <main>Main</main>
  <aside>Aside</aside>
  <footer>Footer</footer>
</div>

CSS:

.container {
  max-width: 800px;
  margin: 2em auto;
  display: grid;
  grid-template-columns: 3fr 1fr;
  grid-template-rows: repeat(3,auto);
  grid-gap: 1rem;
}

.container header {
  grid-area: 1/1/2/3;
}

.container main {
  grid-area: 2/1/3/2;
}

.container aside {
  grid-area: 2/2/3/3;
}

.container footer {
  grid-area: 3/1/4/3;
}

.container > * {
  background-color: #ddd;
  padding: 1rem;
}

Ми створюємо дві колонки з властивістю grid-template-columns, а три рядки — з властивістю grid-template-rows. Функція repeat() створює три рядки з автоматичною висотою.

Потім у grid-елементах (header, main, aside, footer) ми визначаємо скільки місця вони займатимуть, використовуючи властивість grid-area.

Flexbox обгортки vs Grid обгорток

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

Розглянемо відмінності на прикладі. Створюємо два рядки та розміщуємо в кожному по шість div.

<h2>Flexbox</h2>
<div class="row-flex">
    <div>1 2 3  4 5 6 7 8 9 0</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
</div>
 
<h2>Grid</h2>
<div class="row-grid">
    <div>1 2 3  4 5 6 7 8 9 0</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
</div>

Тепер ми будемо використовувати Flexbox для першого рядка і Grid для другого:

/* Flexbox */
.row-flex {
  margin: 40px auto;
  max-width: 600px;
  display: flex;
  flex-wrap: wrap;
}
.row-flex div {
  border: 1px dashed gray;
  flex: 1 1 100px;
  text-align: center;
  padding: 12px;
}
/* Grid */
.row-grid {
  margin: 40px auto;
  max-width: 600px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
.row-grid div {
  border: 1px dashed gray;
  text-align: center;
  padding: 12px;
}

Для першого рядка ми вказали flex: 1 1 100px, щоб визначити базову ширину 100px для flex-елементів і дозволити їм рости та стискатися.

Для огортання flex-елементів всередині flex-контейнера встановлюємо wrap для властивості flex-wrap. Значенням за замовчуванням є nowrap.

Для другого рядка використовуємо властивість grid-template-columns для створення колонок з мінімальною шириною 100px, заданою функцією minmax(). Функція repeat() потрібна для багаторазового створення стовпців:

Grid vs Flexbox: що обрати?

Краса Grid та Flexbox у можливості розтягувати та стискати елементи залежно від кількості доступного місця. Flexbox робить так з властивостями flex-grow та flex-shrink, a Grid – поєднуючи функції minmax() та auto-fill всередині властивості grid-template-columns.

Подивіться уважно як виштовхується вниз п'ята та шоста клітинка. З Flexbox клітинки п'ять та шість не зберігають розмір. А з Grid вони не відрізняються від інших клітинок у сітці.

Коли flex-елемент огортається та виштовхується на новий рядок, алгоритм Flexbox обробляє його як частину іншого flex-контейнера. Отже, виштовхуваний елемент втрачає свій контекст.

Така поведінка може бути використана, наприклад, у формі оформлення підписки:

Grid vs Flexbox: що обрати?

Створимо таку форму:

<div class="subscriber-form-container">
  <form>
    <input type="email" placeholder="Email Address">
    <input type="text" placeholder="Name">
    <input type="submit" value="Subscribe">
  </form>
</div>

Та додамо трохи стилів:

.subscriber-form-container {
  max-width: 650px;
  margin: 40px auto;
  border: 1px dashed gray;
  box-sizing: border-box;
}
.subscriber-form-container form {
  display: flex;
  flex-wrap: wrap;
}
.subscriber-form-container form input {
  margin: 6px;
  padding: 0.4rem;
  box-sizing: border-box;
}
.subscriber-form-container form input{
  flex: 1 1 150px;
}
.subscriber-form-container form input[type="email"] {
  flex: 2 1 300px;
}

Властивість flex є скороченням трьох властивостей: flex-grow, flex-shrink, flex-basis. Ми хочемо, щоб ширина поля email була вдвічі більшою за ширину двох інших input-елементів. Використаємо для цього flex-grow та flex-basis.

Властивість flex-grow для input-елементів має значення 1, а властивість email2. Якщо буде доступний додатковий простір, елемент email поля збільшиться вдвічі у порівнянні з іншими input-елементами.

У нашому випадку Flexbox перевершує Grid. Ви могли б використовувати деякі трюки для повторення такої поведінки з minmax() функцією у CSS Grid, але саме Flexbox найкраще підходить для одновимірних макетів.

Якщо ж вам треба зробити багатовимірний макет з огорненими елементами, що зберігають свою ширину (наприклад, галерея зображень), Grid буде кращим вибором.

Grid vs Flexbox: що обрати?

До речі, ви помітили, що ми не використовуємо медіа-запити тут? Це тому що макети Flexbox та Grid підтримують концепцію адаптивності, а отже зменшується кількість медіа-запитів.

Чи стане Flexbox застарілим у порівнянні з Grid у майбутньому?

Абсолютно ні.

Про це і була стаття. CSS Grid та Flexbox покликані вирішувати різний набір проблем.

На даний момент CSS Grid не має достатньої підтримки в браузерах, щоб створювати веб-сайти для production. Я керуюсь таким правилом: якщо ця фіча охопила понад 95% світового використання, я використовую її в реальних завданнях. Наразі Flexbox охоплює 95% світового використання, а Grid – 87%.

Скоро Grid також отримає добру підтримку серед браузерів і ми зможемо поєднувати Grid та Flexbox для створення дивовижних макетів веб-сайтів, які раніше було неможливо уявити.

Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 6.2K
Приєднався: 7 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація