Tailwind

Layout: Flexbox та Grid через Tailwind

Академічний розбір системи layout у Tailwind CSS: Flexbox — напрямок, вирівнювання, flex-items; CSS Grid — колонки, рядки, span, auto-fit, subgrid. Типові layout-патерни: Navbar, Holy Grail, Card Grid, Dashboard. З живими прикладами та практичними завданнями.

Layout: Flexbox та Grid через Tailwind

Чому Layout — фундамент будь-якого UI

Перш ніж кольори, типографіка чи анімації — існує Layout. Layout відповідає на фундаментальні питання: де розташовуються елементи? як вони групуються? як адаптуються до різних розмірів екрану? Без чіткого розуміння layout навіть найкращий дизайн перетворюється на хаос.

У чистому CSS layout вимагає глибокого знання display, position, float, flex і grid — кожне з власними правилами та взаємодіями. Tailwind не вивчає ці концепції замість вас — він перетворює їх на передбачуваний набір класів, що дозволяє зосередитися на вирішенні layout-задачі, а не на синтаксисі CSS.

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

Ця стаття передбачає знайомство з базовою концепцією Flexbox та Grid. Tailwind — це синтаксис поверх CSS, а не заміна розуміння того, як ці системи працюють. Якщо ви ще не знайомі з ними — рекомендується спочатку прочитати відповідні статті з розділу CSS.

Flexbox у Tailwind: одновимірний layout

Flexbox вирішує задачу одновимірного розподілу: елементи в рядку або колонці з гнучким управлінням вирівнюванням та розподілом простору. Якщо вам потрібно вирівняти елементи по горизонталі або вертикалі, розподілити простір між ними, або побудувати navbar, картку, форму — Flexbox є природним вибором.

Активація: flex та inline-flex

<!-- display: flex — контейнер займає повну ширину рядка -->
<div class="flex">
    <!-- Всі прямі дочірні елементи стають flex-items -->
    <div>Item 1</div>
    <div>Item 2</div>
</div>

<!-- display: inline-flex — контейнер лише за шириною вмісту -->
<span class="inline-flex items-center gap-2 px-3 py-1 bg-indigo-100 rounded-full">
    <span class="size-2 rounded-full bg-indigo-500"></span>
    Активний
</span>
🔒localhost:3000

Різниця між flex та inline-flex аналогічна різниці між block та inline-block: перший займає всю ширину батьківського контейнера, другий — лише стільки, скільки потрібно вмісту.

Напрямок: flex-direction

Визначає основну вісь — напрямок, уздовж якого розміщуються flex-items:

<!-- flex-row: зліва направо (за замовчуванням) -->
<div class="flex flex-row gap-4">
    <div>Ліворуч</div>
    <div>Центр</div>
    <div>Праворуч</div>
</div>

<!-- flex-row-reverse: справа наліво -->
<div class="flex flex-row-reverse gap-4">
    <div>Показується останнім в DOM — але першим візуально</div>
</div>

<!-- flex-col: зверху вниз — для вертикальних layout -->
<div class="flex flex-col gap-4">
    <h2>Заголовок</h2>
    <p>Текст</p>
    <button>CTA</button>
</div>

<!-- flex-col-reverse: знизу вгору -->
<div class="flex flex-col-reverse gap-4">
    <footer>Показується першим в DOM — але внизу</footer>
    <main>Основний контент</main>
</div>
🔒localhost:3000

flex-col — один із найуживаніших класів у Tailwind: картки, форми, sidebar, модальні вікна — все будується у стовпець із потрібними відступами.

Вирівнювання по головній осі: justify-content

Контролює розподіл простору вздовж основної осі (горизонтально при flex-row, вертикально при flex-col):

КласCSSЕфект
justify-startjustify-content: flex-startНа початку (default)
justify-centerjustify-content: centerПо центру
justify-endjustify-content: flex-endВ кінці
justify-betweenjustify-content: space-betweenКрайні впритул, простір між
justify-aroundjustify-content: space-aroundРівний простір навколо кожного
justify-evenlyjustify-content: space-evenlyОднаковий простір між усіма та краями
justify-stretchjustify-content: stretchРозтягнути items
<!-- justify-between: класичний navbar або pagination -->
<div class="flex justify-between items-center px-6 py-4">
    <span class="font-bold">Лого</span>
    <nav class="flex gap-4">...</nav>
    <button>CTA</button>
</div>

<!-- justify-center: центрований контент -->
<div class="flex justify-center gap-4 py-8">
    <button>Так</button>
    <button>Ні</button>
</div>

<!-- justify-end: кнопки вирівняні по правому краю -->
<div class="flex justify-end gap-3 pt-4 border-t">
    <button class="btn-ghost">Скасувати</button>
    <button class="btn-primary">Зберегти</button>
</div>
🔒localhost:3000

Вирівнювання по перехресній осі: align-items

Контролює вирівнювання перпендикулярно основній осі (вертикально при flex-row):

КласCSSЕфект
items-startalign-items: flex-startВерх контейнера
items-centeralign-items: centerЦентр (найуживаніший!)
items-endalign-items: flex-endДно
items-stretchalign-items: stretchРозтягнути по висоті (default)
items-baselinealign-items: baselineПо базовій лінії тексту

items-center — мабуть, найчастіший Flexbox-запит: вертикальне вирівнювання іконки та тексту, кнопки та label, лого та навігації.

<!-- Іконка + текст вирівняні по центру -->
<div class="flex items-center gap-2">
    <svg class="size-5 text-indigo-600">...</svg>
    <span class="text-sm font-medium">Збережено</span>
</div>

<!-- Елементи різної висоти — вирівняні по baseline тексту -->
<div class="flex items-baseline gap-4">
    <h1 class="text-4xl font-black">$99</h1>
    <span class="text-slate-500">/місяць</span>
</div>
🔒localhost:3000

Перенесення: flex-wrap

Визначає, чи переносяться flex-items на новий рядок при переповненні:

<!-- flex-nowrap: не переносити (default) — може виходити за межі -->
<div class="flex flex-nowrap gap-2 overflow-x-auto">
    <!-- горизонтальний скрол при переповненні -->
</div>

<!-- flex-wrap: переносити на новий рядок -->
<div class="flex flex-wrap gap-3">
    <!-- tags, chips, badges — природньо переносяться -->
    <span class="badge">HTML</span>
    <span class="badge">CSS</span>
    <span class="badge">JavaScript</span>
    <span class="badge">React</span>
    <span class="badge">Tailwind</span>
    <span class="badge">Node.js</span>
</div>
🔒localhost:3000

Gap між елементами

gap у Flexbox та Grid працює однаково — задає відступи між flex-items без margin:

<!-- Jednakowy gap між усіма елементами -->
<div class="flex gap-4">...</div>
<!-- 1rem між всіма -->
<div class="flex gap-2">...</div>
<!-- 0.5rem -->
<div class="flex gap-6">...</div>
<!-- 1.5rem -->

<!-- Різний горизонтальний та вертикальний gap -->
<div class="flex flex-wrap gap-x-6 gap-y-3">
    <!-- gap-x: між колонками, gap-y: між рядками при wrap -->
</div>
🔒localhost:3000

Flex-items: властивості дочірніх елементів

Flex-items мають власні властивості, що контролюють їхню поведінку в контейнері:

flex-grow — ріст:

<!-- flex-1: flex: 1 1 0% — рівний розподіл вільного простору -->
<div class="flex">
    <div class="w-48 shrink-0">Фіксований sidebar (shrink-0 — не стискається)</div>
    <div class="flex-1">Основний контент (займає весь залишок)</div>
</div>

<!-- grow: flex-grow: 1 — росте, але не скорочується нижче мінімуму -->
<div class="flex gap-4">
    <div class="grow">Розтягується</div>
    <div class="grow-0">Не розтягується</div>
</div>
🔒localhost:3000

flex-shrink — стиснення:

<!-- shrink: flex-shrink: 1 (default) — стискається при нестачі місця -->
<!-- shrink-0: flex-shrink: 0 — НЕ стискається → для фіксованих елементів -->
<div class="flex">
    <div class="shrink-0 w-64">Sidebar (завжди 256px)</div>
    <div class="min-w-0 flex-1">Контент (стискається при потребі)</div>
</div>
🔒localhost:3000

flex-basis — початковий розмір:

<div class="basis-1/3">33.333% ширини</div>
<div class="basis-64">16rem (256px)</div>
<div class="basis-auto">Розмір за контентом</div>
<div class="basis-0">Нульовий початковий розмір</div>
🔒localhost:3000

Скорочення:

<div class="flex-1">
    <!-- flex: 1 1 0% — рівний розподіл -->
    <div class="flex-auto">
        <!-- flex: 1 1 auto — росте та скорочується -->
        <div class="flex-none"><!-- flex: none — фіксований, не grow/shrink --></div>
    </div>
</div>

Order та Align Self

<!-- order: зміна візуального порядку без зміни DOM -->
<div class="flex">
    <div class="order-2">Другий</div>
    <!-- показується другим -->
    <div class="order-first">Перший</div>
    <!-- order: -9999 → завжди перший -->
    <div class="order-last">Останній</div>
    <!-- order: 9999 → завжди останній -->
    <div class="order-1">Перший числовий</div>
</div>

<!-- self-*: перевизначає align-items для конкретного item -->
<div class="flex items-start h-24">
    <div class="self-start">Вгорі</div>
    <div class="self-center">По центру</div>
    <div class="self-end">Внизу</div>
    <div class="self-stretch">На всю висоту</div>
</div>
🔒localhost:3000

🧪 Практика: Flexbox вирівнювання

Реалізуйте profile-card компонент: аватар size-16 rounded-full ліворуч (shrink-0), праворуч flex-1 flex flex-col gap-1: ім'я (font-bold text-slate-900), посада (text-sm text-slate-500), у footer картки flex justify-between items-center: кількість публікацій та кнопки «Підписатись / Повідомлення». Усе без жодного margin — тільки gap і flex.


Типові Flexbox-патерни

Патерн 1: Navbar — justify-between + items-center

Класичний навбар: лого ліворуч, навігація по центру, CTA-кнопки праворуч. Основа — flex justify-between items-center:

🔒localhost:3000

Патерн 2: Картка з кнопкою завжди внизу — flex-col + grow

Класична задача: сітка карток із різним обсягом тексту, але кнопки на одному рівні. Рішення — flex flex-col на картці та grow на текстовому блоці:

🔒localhost:3000

flex flex-col на картці + grow на секції контенту — класичне рішення «sticky footer всередині картки». Альтернатива: mt-auto на кнопці замість grow на тексті.

🧪 Практика: Flexbox-патерни

Реалізуйте три Flexbox-патерни: (1) Breadcrumb — горизонтальний список посилань із роздільником · між ними через before:content-['·'] before:text-slate-400 або просто між <li>, flex items-center gap-2, активний елемент text-slate-900 font-medium, інші — text-slate-500 hover:text-slate-700; (2) Inline form — input та кнопка в flex flex-row gap-0, input має rounded-r-none, кнопка — rounded-l-none shrink-0; (3) Toast notificationflex items-start gap-3, іконка shrink-0 mt-0.5, текстовий блок flex-1, кнопка закрити shrink-0 self-start.


CSS Grid у Tailwind: двовимірний layout

CSS Grid вирішує задачу двовимірного розміщення: колонки та рядки одночасно. Якщо Flexbox — це «один вимір», то Grid — це «таблиця», де ви повністю контролюєте розміщення елементів у просторі.

Активація та базова структура

<!-- display: grid — займає повну ширину -->
<div class="grid">
    <div>Item 1</div>
    <div>Item 2</div>
</div>

<!-- display: inline-grid — за шириною вмісту -->
<div class="inline-grid grid-cols-2 gap-2">...</div>

Колонки: grid-cols-{n}

grid-cols-{n} задає grid-template-columns: repeat(n, minmax(0, 1fr)) — рівномірний розподіл:

<div class="grid grid-cols-1 gap-4"><!-- 1 колонка (mobile default) --></div>
<div class="grid grid-cols-2 gap-4"><!-- 2 рівних колонки --></div>
<div class="grid grid-cols-3 gap-4"><!-- 3 рівних колонки --></div>
<div class="grid grid-cols-4 gap-4"><!-- 4 рівних колонки --></div>
<div class="grid grid-cols-12 gap-4"><!-- 12-колонна сітка (класика) --></div>

<!-- Адаптивна сітка: mobile-first -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
    <!-- 1 колонка → 2 → 4 залежно від ширини екрана -->
</div>
🔒localhost:3000

Span — розтягнення елементів

col-span-{n} та row-span-{n} дозволяють елементу займати кілька клітинок:

<!-- Колонки -->
<div class="grid grid-cols-4 gap-4">
    <div class="col-span-2">Займає 2 колонки з 4</div>
    <div class="col-span-1">1 колонка</div>
    <div class="col-span-1">1 колонка</div>
    <div class="col-span-full">Займає всю ширину сітки</div>
</div>

<!-- Рядки -->
<div class="grid grid-cols-3 grid-rows-3 gap-4">
    <div class="row-span-2 col-span-2">Велика карта 2×2</div>
    <div class="row-span-2">Висока карта 1×2</div>
    <div>Маленька 1×1</div>
    <div>Маленька 1×1</div>
</div>
🔒localhost:3000

Явне позиціонування: col-start, col-end

<!-- Поставити конкретний елемент у конкретну позицію -->
<div class="grid grid-cols-6 gap-4">
    <div class="col-start-2 col-span-3">
        <!-- Починається з 2-ї колонки, займає 3 колонки (2,3,4) -->
    </div>
    <div class="col-start-5 col-end-7">
        <!-- Від 5-ї до 7-ї лінії (5,6 колонки) -->
    </div>
</div>

<!-- Рядки -->
<div class="grid grid-rows-4">
    <div class="row-start-2 row-span-2">
        <!-- Починається з 2-го рядка, займає 2 рядки -->
    </div>
</div>
🔒localhost:3000

Auto-fit та auto-fill через довільні значення

Для справді адаптивних сіток, де кількість колонок визначається доступним простором — repeat(auto-fill, ...):

<!-- Мінімум 200px на колонку — стільки колонок, скільки влізе -->
<div class="grid grid-cols-[repeat(auto-fill,minmax(200px,1fr))] gap-4">
    <!-- При 640px: 3 колонки. При 320px: 1 колонка. Автоматично! -->
</div>

<!-- auto-fit: приховані порожні колонки (замість auto-fill) -->
<div class="grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-6">
    <!-- auto-fit: колонки стискаються до нуля якщо порожні -->
</div>
🔒localhost:3000

Рядки: grid-rows-{n} та auto-rows

<!-- Фіксована кількість рядків -->
<div class="grid grid-rows-3 grid-flow-col gap-4">
    <!-- 3 рядки, items заповнюються по колонках -->
</div>

<!-- auto-rows: висота кожного рядка -->
<div class="grid grid-cols-3 auto-rows-fr gap-4">
    <!-- fr: рівна частка доступної висоти -->
</div>

<div class="grid grid-cols-3 auto-rows-min gap-4">
    <!-- min: мінімальна висота за вмістом -->
</div>

<!-- Явна висота рядка через довільне значення -->
<div class="grid grid-cols-3 auto-rows-[180px] gap-4">
    <!-- Кожен рядок = 180px -->
</div>
🔒localhost:3000

CSS Subgrid у Tailwind v4

Subgrid дозволяє вкладеному Grid-елементу успадковувати треки батьківської сітки. Це вирішує класичну проблему: вирівнювання внутрішніх елементів між різними картками:

<!-- Без subgrid: заголовки, контент, кнопки "плавають" по висоті -->
<div class="grid grid-cols-3 gap-4">
    <div class="flex flex-col bg-white rounded-xl p-5">
        <h3>Короткий заголовок</h3>
        <p class="grow text-sm mt-2">Довгий опис...</p>
        <button class="mt-4">Дія</button>
    </div>
    <!-- При різному тексті — кнопки на різному рівні -->
</div>

<!-- З subgrid v4: grid-cols-subgrid → успадкування колонок -->
<div class="grid grid-cols-3 gap-4">
    <!-- Кожна картка успадковує рядки батька -->
    <div class="grid row-span-3 [grid-template-rows:subgrid] bg-white rounded-xl p-5 gap-2">
        <h3>Будь-який заголовок</h3>
        <p class="text-sm">Будь-яка довжина тексту</p>
        <button>Кнопка завжди на одному рівні!</button>
    </div>
</div>

<!-- Tailwind v4: grid-cols-subgrid та grid-rows-subgrid як утиліти -->
<div class="grid grid-cols-3">
    <div class="grid grid-cols-subgrid col-span-3">
        <!-- Успадковує 3 колонки батька -->
        <div>1</div>
        <div>2</div>
        <div>3</div>
    </div>
</div>
🔒localhost:3000

🧪 Практика: Grid span та позиціонування

Реалізуйте Bento Grid — популярний layout для features-секцій. Сітка grid-cols-4 auto-rows-[160px] gap-4. Елементи: (1) велика картка col-span-2 row-span-2 з градієнтом і заголовком внизу через flex flex-col justify-end; (2) три маленькі 1×1 картки; (3) широка картка col-span-3 row-span-1 з горизонтальним розміщенням іконки та тексту. Усі картки — rounded-2xl із hover-ефектом.


Типові Grid-патерни

Патерн 1: Card Grid з адаптивністю

🔒localhost:3000

Класичний «Holy Grail» — три секції по вертикалі (header, middle, footer) та дві по горизонталі (sidebar, main) у middle. Рішення — вкладені Grid:

🔒localhost:3000

Ключ до Holy Grail: вкладені Grid. Зовнішній — grid-rows-[auto_1fr_auto] (header rosте не, middle розтягується до залишку висоти, footer не росте). Внутрішній — grid-cols-[220px_1fr] (фіксований sidebar + гнучкий main).

Патерн 3: Bento Grid — Feature Section

🔒localhost:3000

🧪 Практика: Holy Grail з адаптивністю

Реалізуйте повноцінний Holy Grail Layout: (1) sticky header — sticky top-0 z-10 flex justify-between items-center px-6 py-4 bg-white border-b shadow-sm; (2) sidebar w-64 hidden lg:flex flex-col gap-1 p-4 bg-white border-r; (3) main flex-1 p-6 min-w-0 overflow-y-auto; (4) footer border-t px-6 py-4 flex justify-between text-sm text-slate-400. На мобільному sidebar прихований (hidden lg:flex), на desktop — видимий. Весь layout через flex flex-col h-screen на <body> та flex flex-1 overflow-hidden для middle секції.


Адаптивний Layout: breakpoint-варіанти

Tailwind будує адаптивність за принципом mobile-first: клас без префіксу діє на всіх розмірах, а prefix перевизначає від вказаного breakpoint і більше:

Варіантmin-widthТиповий пристрій
(базовий)0pxМобільний
sm:640pxВеликий мобільний / малий планшет
md:768pxПланшет
lg:1024pxНоутбук
xl:1280pxDesktop
2xl:1536pxВеликий монітор
<!-- Mobile-first підхід -->
<div
    class="
    grid grid-cols-1       /* Mobile: 1 колонка */
    sm:grid-cols-2         /* Tablet: 2 колонки */
    lg:grid-cols-4         /* Desktop: 4 колонки */
    gap-4
"
>
    <!-- Flex-напрямок за breakpoint -->
    <div
        class="
    flex flex-col          /* Mobile: вертикально */
    md:flex-row            /* Tablet+: горизонтально */
    gap-4
"
    >
        <!-- Показ/приховання -->
        <aside class="hidden lg:block w-64"><!-- Sidebar: тільки desktop --></aside>
        <button class="block lg:hidden"><!-- Hamburger: тільки mobile --></button>

        <!-- Ширина кнопки -->
        <button
            class="
    w-full                 /* Mobile: на всю ширину */
    sm:w-auto              /* Tablet+: по вмісту */
    px-6 py-2 bg-indigo-600 text-white rounded-lg
"
        ></button>
    </div>
</div>

Tailwind v4: max-* breakpoint-варіанти

Tailwind v4 додав верхні обмеження breakpoint — тепер можна таргетувати конкретний діапазон:

<!-- Тільки на мобільному (до sm) -->
<p class="max-sm:text-center">Центрований тільки на мобільному</p>

<!-- Тільки між md та lg -->
<div class="md:max-lg:flex-col">Колонка тільки на tablet</div>

<!-- Тільки на мобільному: max-md (до md) -->
<nav class="max-md:hidden">Приховано на мобільному</nav>
/* Таблиця max-* breakpoint */
/* max-sm  → @media (max-width: 639px) */
/* max-md  → @media (max-width: 767px) */
/* max-lg  → @media (max-width: 1023px) */
/* max-xl  → @media (max-width: 1279px) */
/* max-2xl → @media (max-width: 1535px) */

🧪 Практика: адаптивний pricing table

Реалізуйте таблицю тарифів із трьома планами (Starter, Pro, Enterprise). На мобільному — flex flex-col gap-4, на md:grid grid-cols-3 gap-6. Середній тариф (Pro) — виділений: border-2 border-indigo-500 shadow-xl scale-105, badge «Найпопулярніший» через absolute -top-4 left-1/2 -translate-x-1/2. Кожен тариф — flex flex-col, список переваг через divide-y divide-slate-100, кнопка — mt-auto.


Position та Z-Index у Tailwind

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

Найпоширеніший патерн: елемент з absolute позиціонуванням прив'язується до relative предка:

<!-- relative = точка відліку для всіх absolute дочірніх -->
<div class="relative">
    <!-- Кутовий badge -->
    <span class="absolute top-2 right-2 px-2 py-0.5 bg-red-500 text-white text-xs rounded-full"> New </span>

    <!-- Hover overlay через inset-0 (= top+right+bottom+left = 0) -->
    <div
        class="absolute inset-0 bg-black/50 rounded-xl
                flex items-center justify-center text-white
                opacity-0 hover:opacity-100 transition-opacity"
    >
        Переглянути
    </div>

    <!-- Контент картки -->
    <img src="..." class="w-full h-48 object-cover rounded-xl" />
</div>
🔒localhost:3000

Корисні inset-* комбінації:

<div class="absolute inset-0">
    <!-- top + right + bottom + left = 0 (повне накриття) -->
    <div class="absolute inset-x-0 top-0">
        <!-- ширина 100%, прикріплена до верху -->
        <div class="absolute inset-x-0 bottom-0"><!-- ширина 100%, прикріплена до низу --></div>
    </div>
</div>

Sticky елементи

<!-- Sticky navbar: залишається вгорі при scroll -->
<nav class="sticky top-0 z-50 bg-white border-b border-slate-200 shadow-sm">
    <!-- z-50: поверх усього вмісту -->
</nav>

<!-- Sticky sidebar в межах батька -->
<aside class="sticky top-24 h-fit">
    <!-- top-24 = 6rem = відступ нижче navbar (60px + padding) -->
    <!-- h-fit = висота за вмістом, не розтягується -->
</aside>
🔒localhost:3000

Z-Index шкала

<div class="z-0">/* z-index: 0 — базовий рівень */</div>
<div class="z-10">/* z-index: 10 — трохи вище */</div>
<div class="z-20">/* z-index: 20 */</div>
<div class="z-30">/* z-index: 30 */</div>
<div class="z-40">/* z-index: 40 */</div>
<div class="z-50">/* z-index: 50 — dropdown, tooltip */</div>
<div class="z-[999]">/* Довільне значення через [] */</div>

<!-- Від'ємний z-index -->
<div class="-z-10">/* z-index: -10 — під всіма */</div>

Завдання для самоперевірки


Попередня стаття: Utility-класи: основи та системаНаступна стаття: Кастомізація теми через @theme

Copyright © 2026