Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «CSS grid layout». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**CSS Grid Layout** - це двовимірна система макетів, яка ділить контейнер на рядки та стовпці і дозволяє розміщувати елементи по обох осях одночасно. ```css .container { display: grid; grid-template-columns: 200px 1fr; grid-template-rows: auto 1fr auto; gap: 1rem; } ``` **Ключове:** на відміну від Flexbox (одна вісь), Grid керує рядками і стовпцями разом - це інструмент для структури сторінки: header, sidebar, footer.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**CSS Grid Layout** - це двовимірна система CSS-макетів, яка ділить контейнер на рядки та стовпці і дозволяє точно розміщувати елементи по обох осях одночасно. ## Теорія ### TL;DR - Уяви таблицю Excel: задаєш колонки і рядки, кидаєш елементи в конкретні клітинки - Головна різниця з Flexbox: Grid керує рядками І стовпцями разом; Flexbox працює по одній осі - Grid - для каркасу сторінки (header, sidebar, content, footer); Flexbox - всередині клітинок для вирівнювання компонентів - Одиниця `fr` розподіляє вільний простір після того, як фіксовані та `auto`-треки вже розраховані - `grid-template-areas` дає тобі ASCII-карту макету прямо в CSS ### Швидкий приклад ```css .container { display: grid; grid-template-columns: 1fr 2fr 1fr; /* вузька | широка | вузька */ grid-template-rows: auto 1fr auto; /* під контент | гнучкий | під контент */ gap: 1rem; height: 100vh; } ``` Три стовпці (рівний, подвійний, рівний), три рядки (під вміст, гнучкий, під вміст). Елементи заповнюються зліва направо, зверху вниз за замовчуванням. Додай `grid-template-areas` - і отримаєш іменований макет, який читається з першого погляду. ### Grid проти Flexbox Grid створює явну сітку треків на контейнері і розміщує елементи в місцях їх перетину. Flexbox вишиковує елементи по одній осі та переносить їх при необхідності. Одне не замінює інше. Grid - це скелет сторінки. Flexbox - м'язи всередині кожної клітинки. Практичне правило: якщо потрібно керувати рядками і стовпцями разом (дашборд, журнальний макет, елементи що перекриваються) - Grid. Якщо просто рядок кнопок або список карток що переносяться - Flexbox простіший. ### Коли використовувати - Повний макет сторінки з header, sidebar, content, footer: Grid з `grid-template-areas` - Дашборд з панелями що охоплюють кілька стовпців: Grid з `grid-column: 1 / -1` - Навігаційна панель з посиланнями по горизонталі: Flexbox - Внутрішня структура картки (іконка + текст): Flexbox - Адаптивна галерея з невідомою кількістю елементів: `repeat(auto-fill, minmax(250px, 1fr))` - Два елементи що перекриваються без `position: absolute`: Grid, одна зона клітинок, різний `z-index` ### Таблиця порівняння | Ознака | CSS Grid | Flexbox | |---|---|---| | Виміри | 2D: рядки і стовпці | 1D: головна вісь + поперечна | | Розміщення | Явні лінії, іменовані зони, auto-flow | Порядок у потоці з переносом | | Охоплення (span) | Нативний `grid-column: 1 / 3` | Недоступно нативно | | Іменовані зони | Так, `grid-template-areas` | Ні | | Найкраще для | Макети сторінок, дашборди, перекриття | Навбар, картки, групи кнопок | ### Основні властивості **Властивості контейнера** задають структуру сітки. `grid-template-columns` і `grid-template-rows` визначають розміри треків. `gap` додає простір тільки між треками (не по зовнішніх краях). `grid-template-areas` візуально описує іменовані зони. ```css .layout { display: grid; grid-template-areas: "header header header" "sidebar content aside" "footer footer footer"; grid-template-columns: 200px 1fr 200px; grid-template-rows: auto 1fr auto; gap: 1rem; } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .content { grid-area: content; } .footer { grid-area: footer; } ``` Без float. Без clearfix. Без `position: absolute`. Весь макет сторінки - шість рядків CSS. **Властивості елементів** керують розміщенням і вирівнюванням. `grid-column: 1 / 3` - від лінії 1 до лінії 3. `grid-column: 1 / -1` - завжди повна ширина рядка, скільки б стовпців не було. `justify-self` і `align-self` вирівнюють один конкретний елемент у клітинці, не зачіпаючи сусідів. ### repeat() та minmax() `repeat(3, 1fr)` - три рівні стовпці. Корисніший шаблон: `repeat(auto-fill, minmax(250px, 1fr))`. Він створює стільки стовпців, скільки вміщається, кожен щонайменше 250px, і розподіляє залишок пропорційно. Заміни `auto-fill` на `auto-fit` - порожні хвостові треки зникнуть, елементи розтягнуться на весь рядок. Різниця помітна коли елементів менше, ніж можливих стовпців. `auto-fill` залишає «примарні» треки. `auto-fit` їх прибирає. Я не раз бачив як `fr`-стовпці падають майже до нуля на маленьких екранах. Рішення завжди одне: `minmax(200px, 1fr)` замість голого `1fr`. Одиниця `fr` розподіляє тільки вільний простір - якщо його немає, треки стискаються до мінімального вмісту. ### Як браузер обробляє Grid `display: grid` запускає grid formatting context (контекст форматування сітки). Спочатку розраховуються фіксовані треки, потім `auto`, потім `fr`-одиниці отримують залишок. Явно розміщені елементи ідуть першими, решта auto-flow заповнює вільні клітинки. Зміна розміру вікна запускає алгоритм заново - тому складні комбінації `minmax` і `fr` на великих сітках можуть коштувати більше на resize, ніж простий Flexbox. ### Типові помилки **Встановлення `justify-items: center` щоб відцентрувати один елемент.** `justify-items` центрує кожен елемент у кожній клітинці. Для одного конкретного елемента - `justify-self: center` саме на ньому. ```css /* Рухає всі елементи - напевно не те що потрібно */ .container { justify-items: center; } /* Рухає тільки цей */ .featured { justify-self: center; } ``` **Очікування що `gap` додасть відступи по зовнішніх краях.** `gap` додає простір тільки між треками. Зовнішніх відступів за специфікацією немає. Для зовнішнього простору - `padding` на контейнері. **Голий `1fr` на маленьких екранах.** `fr` бере тільки вільний простір. Якщо його немає - треки стискаються до мінімуму. Використовуй `minmax(200px, 1fr)`. ```css /* Нестабільно на маленьких екранах */ grid-template-columns: repeat(3, 1fr); /* Надійніше */ grid-template-columns: repeat(3, minmax(200px, 1fr)); ``` **Вкладені сітки без висоти.** Дочірній `display: grid` не має висоти якщо батьківська клітинка не розтягує його. `align-items: stretch` є за замовчуванням, але може бути перевизначений. Перевіряй це першим коли вкладена сітка раптово схлопується. **Перекриття елементів у неправильному порядку.** Елементи перекриваються за порядком у DOM за замовчуванням. Додай явні значення `z-index` щоб контролювати що зверху. Grid-елементи приймають `z-index` так само як позиційовані елементи коли займають пересічні зони. ### Де зустрічається в реальних проєктах - Tailwind CSS: `grid grid-cols-12 gap-4` для адаптивних дашбордів - Bootstrap 5: `row g-3` з колонками для карткових сіток - Material-UI (MUI): `Grid container spacing={2}` в React-застосунках - Chakra UI: `SimpleGrid columns={4}` для авто-потокових галерей - GitHub: список файлів у репозиторії використовує grid для іконки, назви і колонки дій ### Питання для поглиблення **Q:** Яка різниця між `grid-template` і `grid-template-columns`? **A:** `grid-template` - скорочення, що поєднує `grid-template-columns`, `grid-template-rows` і `grid-template-areas` в одному оголошенні. Окремі властивості зручніші коли потрібно змінити тільки один вимір без впливу на інші. **Q:** Як працює імпліцитна сітка (implicit grid)? **A:** Елементи розміщені за межами явної сітки автоматично створюють нові треки. `grid-auto-rows` і `grid-auto-columns` задають розміри цих треків. `grid-auto-flow: dense` заповнює прогалини перевпорядковуючи елементи візуально, DOM-порядок при цьому не змінюється. **Q:** Що таке subgrid? **A:** Subgrid (CSS Grid Level 2) дозволяє дочірній сітці вирівнювати свої треки за батьківською замість створення незалежних. Задається `grid-template-rows: subgrid` на дочірньому елементі. Зручно для вирівнювання контенту між кількома картками в одному ряду. Підтримка в сучасних браузерах є станом на кінець 2024 року. **Q:** Коли перерахунок Grid дорожчий ніж Flexbox? **A:** Складні комбінації `minmax` і `fr` перераховуються при кожній зміні розміру вікна. Велика сітка з багатьма `auto`-треками запускає важчий алгоритм ніж простий Flexbox-ряд. Профілюй у Chrome DevTools Performance panel перед оптимізацією. **Q:** Чи можна зробити masonry layout на чистому CSS Grid? **A:** `grid-template-rows: masonry` є в специфікації і був доступний за флагом у Firefox. Станом на 2024 рік жоден стабільний браузер не підтримує це. Поточні запасні варіанти - CSS `column-count` або JavaScript. Знання де специфікація і де реальна реалізація - ознака senior рівня. ## Приклади ### Адаптивний макет сторінки ```css .page { display: grid; grid-template-areas: "header" "content" "footer"; grid-template-rows: auto 1fr auto; min-height: 100vh; gap: 1rem; } @media (min-width: 768px) { .page { grid-template-areas: "header header" "sidebar content" "footer footer"; grid-template-columns: 250px 1fr; } } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .content { grid-area: content; } .footer { grid-area: footer; } ``` На мобільному все складається вертикально. Від 768px sidebar з'являється зліва. Вся зміна - це дві властивості всередині media query. ### Дашборд з панелями що охоплюють кілька рядків ```css .dashboard { display: grid; grid-template-columns: 250px 1fr 300px; grid-template-rows: auto 1fr auto; grid-template-areas: "sidebar header stats" "sidebar content stats" "sidebar footer footer"; gap: 2rem; min-height: 100vh; } .sidebar { grid-area: sidebar; } .header { grid-area: header; } .content { grid-area: content; } .stats { grid-area: stats; } .footer { grid-area: footer; } ``` Sidebar займає всі три рядки зліва. Панель stats справа охоплює два рядки. Footer перекриває останні два стовпці. Ця структура лежить в основі більшості адмін-панелей на Next.js і Remix. ### Елементи що перекриваються ```css .canvas { display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 100px); gap: 10px; } .card-red { grid-column: 1 / 3; /* верхній лівий блок 2x2 */ grid-row: 1 / 3; background: #e55; z-index: 1; } .card-blue { grid-column: 2 / 4; /* перекриває правий нижній кут червоного */ grid-row: 2 / 4; background: #55e; z-index: 2; } ``` Синій перекриває правий нижній кут червоного без обрізки. Без абсолютного позиціонування. `z-index` на grid-елементах працює так само як на позиційованих елементах коли вони займають пересічні зони сітки.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.