Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Порівняння flexbox та CSS grid». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Flexbox** для одновимірних макетів (рядок або стовпець). **CSS Grid** для двовимірних (рядки і стовпці разом). ```css /* Flexbox: одна вісь */ .nav { display: flex; justify-content: space-between; align-items: center; } /* Grid: дві осі */ .layout { display: grid; grid-template-columns: 240px 1fr; } ``` **Правило вибору:** Flexbox для компонентів і одновимірних потоків; Grid для структури сторінки і двовимірних макетів.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Flexbox** будує макети вздовж однієї осі (рядок або стовпець); **CSS Grid** будує на двох осях одразу (рядки і стовпці разом). ## Теорія ### Коротко - Flexbox = один ряд сидінь в автобусі: елементи течуть вздовж однієї осі та розтягуються або стискаються - Grid = схема кварталу: ти визначаєш вулиці І проспекти, елементи розміщуються на перетинах - Головна різниця: Flexbox розподіляє простір вздовж однієї осі; Grid контролює обидві одночасно - Одновимірний макет (навбар, група кнопок, ряд карток)? Flexbox. Сторінка або дашборд? Grid - Вони добре поєднуються: Grid для каркасу сторінки, Flexbox всередині кожної клітинки ### Швидкий приклад Однаковий візуальний результат, різний рівень контролю: ```html <!-- Flexbox: елементи течуть вздовж головної осі --> <div class="flex-row"> <div class="item">Nav</div> <div class="item">Logo</div> <div class="item">Login</div> </div> <!-- Grid: треки визначено заздалегідь --> <div class="grid-layout"> <header>Header</header> <aside>Sidebar</aside> <main>Content</main> </div> ``` ```css /* Flexbox: одна вісь, простір розподіляється між елементами */ .flex-row { display: flex; justify-content: space-between; align-items: center; } /* Grid: дві осі, зони визначено явно */ .grid-layout { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: 60px auto; grid-template-areas: "header header" "sidebar content"; } ``` Flexbox нічого не знає про рядки. Grid не займається потоком вмісту. Саме в цьому розриві й лежить рішення про вибір. ### Ключова різниця Flexbox починає з контенту і розподіляє навколо нього простір. Елементи розтягуються, стискаються, переносяться на новий рядок, але завжди вздовж однієї осі. Grid починає зі структури: спочатку визначаєш треки, потім елементи їх заповнюють. Тому Grid дозволяє елементам перекривати кілька рядків і стовпців незалежно, а елементи Flexbox завжди рухаються по потоку. Вкласти Flexbox всередину клітинки Grid - звична практика, яка покриває більшість реальних макетів. ### Коли що використовувати - Навбар з логотипом і посиланнями: Flexbox (`justify-content: space-between`) - Ряд карток однакової висоти: Flexbox (`align-items: stretch`) - Макет з хедером, сайдбаром, контентом і футером: Grid - Дашборд з асиметричними панелями різного розміру: Grid (`grid-template-areas`) - Центрування одного елемента: підходять обидва (`display: flex; place-items: center` або `display: grid; place-items: center`) - Галерея де деякі елементи займають кілька колонок: Grid (`grid-column: span 2`) - Компонент всередині клітинки Grid, наприклад група кнопок у nav-зоні: Flexbox ### Таблиця порівняння | Аспект | Flexbox | CSS Grid | |---|---|---| | Виміри | 1D (рядок або стовпець) | 2D (рядки і стовпці) | | Головна сила | Розподіл простору вздовж однієї осі | Явне розміщення та перекриття елементів | | Поведінка контейнера | Елементи займають доступний простір | Треки визначено заздалегідь | | Керування елементами | `flex-grow`, `flex-shrink`, `flex-basis`, `order` | `grid-area`, `grid-column`, `grid-row`, `place-self` | | Вирівнювання | `justify-content`, `align-items`, `align-self` | `justify-items`, `align-items`, `place-items`, `place-content` | | Перекриття елементів | Складно | Нативна підтримка через спільну grid-зону | | Підтримка браузерів | IE10+, повна підтримка в сучасних | IE11 частково; subgrid з Chrome 117 | | Коли використовувати | Навбари, кнопки, ряди карток, центрування | Макети сторінок, дашборди, галереї | ### Як браузер це обробляє Коли браузер бачить `display: flex`, він створює flex formatting context. Спочатку обраховує гіпотетичний розмір кожного елемента через `flex-basis`, потім розподіляє залишковий простір відповідно до `flex-grow`. Перенос на новий рядок відбувається тільки при `flex-wrap: wrap`. `display: grid` створює grid formatting context. Браузер будує карту треків з `grid-template-columns` і `grid-template-rows`, потім розміщує елементи або за явним `grid-area`, або через алгоритм автоматичного розміщення. Grid розраховує треки одноразово на початку; Flexbox перераховує при кожному reflow. Для довгих списків (1000+ елементів) Flexbox зазвичай швидший, бо кешування рядків простіше ніж розрахунок grid-треків. ### Типові помилки **Помилка 1: `flex-direction: column` для макету з сайдбаром і основним контентом** ```css /* Неправильно: flex-direction column складає елементи зверху вниз */ .layout { display: flex; flex-direction: column; } /* Виправлення: Grid створює справжню структуру з колонками поруч */ .layout { display: grid; grid-template-areas: "sidebar main"; grid-template-columns: 240px 1fr; } ``` Це найпоширеніша помилка з макетами, яку я бачу на код-рев'ю. Розробники, які добре знають Flexbox, тягнуться до `flex-direction: column` коли потрібні колонки поруч, а він просто складає елементи вертикально. **Помилка 2: `align-items: center` на Grid для повного центрування** ```css /* Неправильно: центрує тільки по поперечній осі кожного треку */ .grid { display: grid; align-items: center; } /* Виправлення: центрує по обох осях */ .grid { display: grid; place-items: center; } ``` `align-items` відповідає за block-вісь. `justify-items` - за inline-вісь. `place-items` - скорочення для обох, і саме воно потрібне для справжнього центрування. **Помилка 3: `justify-content: space-between` з елементами різного розміру** ```css /* Виглядає нерівномірно коли ширина елементів різна */ .nav { display: flex; justify-content: space-between; } /* Виправлення: gap дає передбачуваний відступ */ .nav { display: flex; gap: 1rem; } ``` `space-between` розподіляє вільний простір між елементами. Якщо ширина елементів різна, проміжки візуально відрізняються. `gap` дає однакові відступи незалежно від розміру елементів і не виходить за зовнішні краї після перенесення рядка. **Помилка 4: Відсутність `min-height: 0` у дочірніх елементах flex-колонки** ```css /* Елемент відмовляється стискатись і виходить за межі батька */ .sidebar-item { display: flex; flex-direction: column; /* Відсутній: min-height: 0 */ } /* Виправлення */ .sidebar-item { display: flex; flex-direction: column; min-height: 0; /* Дозволяє стискатись нижче розміру контенту */ overflow: auto; } ``` Flex-елементи за замовчуванням мають `min-height: auto`, що не дозволяє стискатись нижче розміру контенту. В колонкових макетах це викликає переповнення. `min-height: 0` знімає це обмеження. **Помилка 5: Subgrid без відповідних треків у батьківському елементі (Chrome 117+)** ```css /* Батько визначає тільки два стовпці */ .grid-parent { display: grid; grid-template-columns: 1fr 2fr; } /* Subgrid автоматично використовує auto якщо кількість треків не збігається */ .grid-child { display: grid; grid-template-columns: subgrid; } ``` Subgrid успадковує треки батьківського елемента. Якщо батько не визначає потрібні треки, subgrid повертається до `auto` і вирівнювання ламається без жодних помилок. Спочатку визнач явні треки в батьківському елементі. ### Де це зустрічається - React і Next.js: Flexbox для компонентів (кнопки та навбари в Chakra UI); Grid для структури додатку (дашборд Vercel) - Tailwind CSS: `flex space-x-4` для inline-списків; `grid-cols-12` для каркасу сторінок у темах Shopify - Bootstrap 5: `.d-flex .justify-content-between` побудований на Flexbox; складні форми з кількома колонками використовують Grid - Material UI: Flexbox у компонентах Card і List; Grid у таблицях даних ### Питання на співбесіді **Q:** Яка різниця між `justify-content` і `justify-items`? **A:** `justify-content` розподіляє простір між треками або елементами на рівні контейнера. `justify-items` вирівнює кожен елемент всередині його власної grid-зони. У Flexbox є `justify-content`, але немає `justify-items` - ця властивість працює тільки в Grid. **Q:** Чим відрізняється `flex-basis` від `width`? **A:** `flex-basis` - це початковий розмір елемента до застосування `flex-grow` і `flex-shrink`. `width` - це розмір у блоковій моделі. Якщо задані обидва, у flex-контексті перемагає `flex-basis`. `flex-basis: 0` змушує всі елементи починати з нуля і рівномірно зростати. **Q:** Як працює `grid-auto-flow: dense`? **A:** Коли spanning-елементи залишають порожні місця в сітці, `dense` наказує браузеру заповнювати їх меншими елементами з пізніших позицій у DOM. Це покращує щільність сітки, але змінює візуальний порядок відносно DOM-порядку, що може ускладнити навігацію клавіатурою. **Q:** Чому `gap` краще за margins у flex або grid-контейнерах? **A:** `gap` застосовується тільки між елементами, не на зовнішніх краях. Margins на дочірніх елементах накопичуються і можуть створювати подвійні відступи по краях або після перенесення рядка. `gap` коректно працює в обох контекстах. **Q:** Що таке subgrid і коли він реально потрібен? **A:** Subgrid дозволяє вкладеній сітці успадковувати розміри треків батьківської. Без нього картка всередині Grid-клітинки визначає власні внутрішні треки, які не збігатимуться з картками у сусідніх клітинках. З subgrid всі картки ділять однакові row-треки і їх контент вирівнюється по колонках. Доступно в Chrome 117+, Firefox 71+, Safari 16+. Для старших браузерів CSS custom properties на спільному батьківському елементі - практична альтернатива. ## Приклади ### Навбар на Flexbox (React, production-патерн) ```jsx function Navbar() { return ( <nav style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '1rem 2rem', borderBottom: '1px solid #eee' }}> <span style={{ fontWeight: 'bold' }}>Logo</span> <ul style={{ display: 'flex', listStyle: 'none', gap: '2rem', margin: 0 }}> <li>Home</li> <li>About</li> <li>Contact</li> </ul> <button>Login</button> </nav> ); } ``` Логотип зліва, навігація з рівними відступами, кнопка входу справа. Внутрішній `ul` теж flex-контейнер. Це і є патерн «Grid для каркасу, Flexbox всередині» на практиці. ### Макет сторінки на CSS Grid ```css .app { display: grid; grid-template-columns: 240px 1fr; grid-template-rows: 60px 1fr 40px; grid-template-areas: "header header" "sidebar content" "footer footer"; min-height: 100vh; } header { grid-area: header; } aside { grid-area: sidebar; } main { grid-area: content; } footer { grid-area: footer; } ``` Іменовані зони роблять структуру читабельною з першого погляду. Зміни `grid-template-columns` на `1fr` в media query - і весь макет перебудовується автоматично. ### Галерея з перекриттям колонок ```css .gallery { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; } /* Виділений елемент займає дві перші колонки */ .gallery .featured { grid-column: span 2; } ``` Перкриття елементів - це те, де Grid не має аналога у Flexbox. Зробити один flex-елемент шириною двох колонок при збереженні спільної сітки неможливо. Grid підтримує це нативно.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.