Пять режимов позиционирования
| Класс | Поведение | Типичный случай |
|---|---|---|
static | обычный поток, смещения игнорируются | значение по умолчанию |
relative | остаётся в потоке, но можно сместить и стать «якорем» | родитель для абсолютных детей |
absolute | выпадает из потока, отсчёт от позиционированного предка | бейдж, крестик, подсказка |
fixed | привязан к окну, не двигается при прокрутке | модальное окно, панель уведомлений |
sticky | в потоке, пока не дойдёт до границы — потом «прилипает» | шапка таблицы, боковая навигация |
Обычный поток — это очередь: каждый занимает своё место и толкает соседей.
absolute — человек, который вышел из очереди и встал у стены:
очередь его больше не замечает, а место он выбирает относительно стены.
Стена — ближайший предок с relative. Если стены нет, «стеной»
становится вся страница.
Пара relative + absolute
Это самая частая конструкция во всём уроке:
<div class="flex gap-6">
<div class="relative inline-flex size-12 items-center justify-center rounded-lg bg-slate-100 text-lg">
🔔
<span class="absolute -top-1 -right-1 flex size-5 items-center justify-center rounded-full bg-rose-600 text-[10px] font-semibold text-white">7</span>
</div>
<div class="relative w-56 rounded-lg border border-slate-200 bg-white p-4 text-sm text-slate-700">
Карточка с крестиком
<button class="absolute top-2 right-2 rounded p-1 text-slate-400 hover:bg-slate-100 hover:text-slate-600" aria-label="Закрыть">✕</button>
</div>
</div>
<div class="relative">
<span class="absolute -top-1 -right-1">7</span>
</div>
inset: короткая запись смещений
inset-0— все четыре стороны в ноль, элемент растянут на родителя;inset-x-4/inset-y-2— по горизонтали / вертикали;top-0,right-4,-bottom-2— отдельные стороны;start-0/end-0— логические стороны для RTL.
<div class="relative h-32 overflow-hidden rounded-lg bg-linear-to-br from-sky-400 to-indigo-500">
<div class="absolute inset-0 bg-slate-900/40"></div>
<div class="absolute inset-x-4 bottom-4 text-sm font-medium text-white">inset-0 — затемнение, inset-x-4 bottom-4 — подпись</div>
</div>
sticky: липкие элементы
sticky — гибрид: элемент ведёт себя как обычный, пока не
достигнет заданной границы, после чего фиксируется. Обязательно указывать,
к чему липнуть: sticky top-0.
- Строка 1
- Строка 2
- Строка 3
- Строка 4
- Строка 5
- Строка 6
- Строка 7
- Строка 8
<div class="h-48 overflow-y-auto rounded-lg border border-slate-200">
<div class="sticky top-0 border-b border-slate-200 bg-white/95 px-4 py-2 text-xs font-semibold text-slate-900">Липкая шапка — прокрутите блок</div>
<ul class="divide-y divide-slate-100 text-sm text-slate-700">
<li class="px-4 py-2">Строка 1</li>
<li class="px-4 py-2">Строка 2</li>
<li class="px-4 py-2">Строка 3</li>
<li class="px-4 py-2">Строка 4</li>
<li class="px-4 py-2">Строка 5</li>
<li class="px-4 py-2">Строка 6</li>
<li class="px-4 py-2">Строка 7</li>
<li class="px-4 py-2">Строка 8</li>
</ul>
</div>
overflow: hidden или overflow: auto — прокрутка
«съедается» этим предком. Это причина 90% случаев «sticky не липнет».Слои: z-index и контекст наложения
Классы z-0, z-10, z-20, …,
z-50 задают порядок наложения. Но работает он только среди
«соседей» внутри одного контекста наложения.
Новый контекст создаёт не только z-index у позиционированного
элемента, но и transform, opacity меньше 1,
filter, will-change. Поэтому z-50
внутри блока с opacity-90 никогда не окажется выше соседнего блока
с z-10.
<!-- родитель создаёт контекст: transform -->
<div class="translate-y-0">
<div class="z-50">Я не смогу перекрыть соседа родителя</div>
</div>
<div class="relative z-10">Я выше, потому что контекст у нас общий</div>
body. Именно так работают порталы в React и компоненты
Dialog из shadcn/ui (урок 21). Класс isolate
создаёт контекст намеренно — чтобы «запереть» слои внутри блока.overflow: что делать с лишним
| Класс | Поведение | Когда |
|---|---|---|
overflow-hidden | обрезать | скругления, обложки, анимации |
overflow-auto | прокрутка при необходимости | списки, таблицы |
overflow-x-auto | горизонтальная прокрутка | широкие таблицы на мобильных |
overflow-y-scroll | всегда показывать полосу | чтобы контент не «прыгал» |
overflow-visible | показывать выходящее | подсказки, выпадающие меню |
overscroll-contain | не «пробрасывать» прокрутку наружу | модальные окна, боковые панели |
| Клиент | Договор | Менеджер | Сумма |
|---|---|---|---|
| ООО «Ромашка» | 2026-114 | Смирнова | 120 000 |
| ИП Ковалёв | 2026-115 | Титов | 64 500 |
<div class="max-w-sm overflow-x-auto rounded-lg border border-slate-200">
<table class="w-max text-sm">
<thead class="bg-slate-50 text-xs text-slate-500">
<tr><th class="px-4 py-2 text-left">Клиент</th><th class="px-4 py-2 text-left">Договор</th><th class="px-4 py-2 text-left">Менеджер</th><th class="px-4 py-2 text-right">Сумма</th></tr>
</thead>
<tbody class="divide-y divide-slate-100 text-slate-700">
<tr><td class="px-4 py-2">ООО «Ромашка»</td><td class="px-4 py-2">2026-114</td><td class="px-4 py-2">Смирнова</td><td class="px-4 py-2 text-right tabular-nums">120 000</td></tr>
<tr><td class="px-4 py-2">ИП Ковалёв</td><td class="px-4 py-2">2026-115</td><td class="px-4 py-2">Титов</td><td class="px-4 py-2 text-right tabular-nums">64 500</td></tr>
</tbody>
</table>
</div>
Таблица шире контейнера — и это нормально: overflow-x-auto
даёт прокрутить её, не ломая раскладку страницы.