Position: нормальный поток, absolute, relative, fixed, sticky и z-index
В предыдущих статьях курса мы выстроили архитектуру страницы (семантические области и компоненты) и закрепили геометрию элементов (блочная модель, отступы, box-sizing, gap). Теперь добавим третий слой практики: позиционирование.
Важно понимать позиционирование правильно: position не заменяет структуру, Flexbox или Grid. В устойчивой вёрстке позиционирование решает точечные задачи — бейджи, иконки, выпадающие панели, «липкие» шапки, перекрытия, слои.
Нормальный поток документа
Нормальный поток — это базовое поведение браузера, когда элементы идут один за другим согласно типу отображения (display) и правилам блочной/строчной модели.
Блочные элементы занимают всю доступную ширину и идут сверху вниз.
Строчные элементы текут внутри строки и переносятся по словам.
Flex и Grid меняют правила раскладки детей контейнера, но сами контейнеры по-прежнему живут в нормальном потоке (если их не выводить из него позиционированием).Ключевая мысль: пока вы не применили position (или похожие механики), браузер сам решает, где будет элемент, исходя из потока и раскладки.
!Сравнение нормального потока и элемента, выведенного из потока
Какие бывают режимы позиционирования
Свойство position задаёт режим позиционирования элемента.
| Значение position | В потоке? | Что меняется | Типичные применения |
|---|---|---|---|
| static (по умолчанию) | Да | Никаких смещений через top/right/bottom/left | Обычная вёрстка |
| relative | Да | Можно сместить элемент относительно его места в потоке | Небольшие подстройки, создание якоря для absolute |
| absolute | Нет | Элемент позиционируется относительно ближайшего позиционированного предка | Бейджи, иконки, выпадающие меню, оверлеи внутри блока |
| fixed | Нет | Элемент закреплён относительно окна просмотра (viewport) | Липкая панель действий, кнопка «вверх» |
| sticky | Да (до порога) | Элемент ведёт себя как relative, но «прилипает» при прокрутке | Липкая шапка секции, заголовки таблиц |
Справка:
MDN: positionposition: relative
position: relative оставляет элемент в нормальном потоке, но позволяет визуально сдвинуть его с помощью top, right, bottom, left.
Главные свойства relative:
Место элемента в потоке сохраняется, даже если вы его сдвинули.
Сдвиг происходит относительно того места, где элемент был бы в потоке.
relative часто используют как контейнер-якорь для абсолютно позиционированных детей.Пример: сдвиг на 4px вниз и 8px вправо.
Практическое правило: не используйте relative как способ «подогнать» раскладку, если проблему можно решить потоком, gap, Flexbox или Grid. relative хорош для небольших подстроек и для управления слоями/якорями.
position: absolute
position: absolute выводит элемент из нормального потока.
Это означает:
Элемент перестаёт занимать место в раскладке.
Соседи ведут себя так, будто элемента нет.
Элемент можно точно разместить через top/right/bottom/left.Относительно чего считается absolute
Абсолютное позиционирование считается относительно контейнера позиционирования (containing block). В типичном случае это ближайший предок, у которого position не static.
Практическая формула поведения:
Если у родителя (или ближайшего предка) стоит position: relative (или absolute/fixed/sticky), то absolute-элемент будет позиционироваться относительно этого предка.
Если такого предка нет, позиционирование пойдёт относительно начального контейнера (обычно это область документа/viewport, поведение зависит от конкретного кейса и спецификации).Справка:
MDN: Containing blockБазовый паттерн: бейдж внутри карточки
Карточка остаётся в потоке, бейдж выводим из потока и крепим к углу.
Почему здесь уместен absolute:
Бейдж декоративен/вспомогателен и не должен влиять на размеры карточки.
Бейдж логически принадлежит карточке, поэтому якорим его на .card через position: relative.Центрирование absolute-элемента
Один из самых устойчивых способов центрировать абсолютный элемент внутри контейнера — через трансформацию.
Важно: transform меняет визуальное положение, но не возвращает элемент в поток.
Типовые ошибки с absolute
Элемент «улетел» не туда.
Элемент перекрывает соседей и ломает кликабельность.
Размеры контейнера не учитывают содержимое.Частая причина — отсутствие позиционированного предка. Обычно лечится постановкой position: relative на нужный контейнер-компонент.
position: fixed
position: fixed фиксирует элемент относительно окна просмотра. Элемент также выводится из потока.
Свойства fixed:
Элемент «прибит» к viewport и не двигается при прокрутке страницы.
Как и absolute, управляется через top/right/bottom/left.
Часто используется для плавающих кнопок, фиксированных панелей, уведомлений.Пример: кнопка «наверх» в правом нижнем углу.
Справка:
MDN: position: fixedПрактическая осторожность: фиксированные элементы легко перекрывают контент. Обычно им нужно место, либо они должны быть компактными, либо должен быть продуман отступ у body/main.
position: sticky
position: sticky — гибрид: элемент остаётся в потоке как обычный, но при прокрутке внутри области прокрутки начинает вести себя как «прилипший».
Ключевые свойства sticky:
Пока не достигнут порог, элемент ведёт себя как relative.
Когда достигнут порог, элемент «прилипает» как fixed, но в пределах своего контейнера прокрутки.
Для sticky нужно задать хотя бы одно смещение: обычно top.Пример: липкая шапка секции.
Условия, без которых sticky не работает
Чаще всего sticky «не работает» по одной из причин:
Не задано top (или bottom/left/right).
Нет прокрутки (контент не длиннее контейнера).
Родитель/предок создаёт неподходящие условия из-за overflow.По overflow: липкость вычисляется в контексте ближайшего прокручиваемого контейнера. Если вы неожиданно задали overflow: hidden или overflow: auto не там, где думали, липкость может ограничиться другим контейнером.
Справка:
MDN: position: stickyСлои, перекрытие и z-index
Когда элементы перекрывают друг друга, порядок отображения определяется контекстом наложения и z-index.
Базовая логика слоёв
Если два элемента перекрываются, побеждает тот, который выше по правилам наложения.
z-index работает только там, где элемент участвует в слоёвом контексте.Справка:
MDN: z-index
MDN: Stacking contextКогда z-index имеет смысл
Упрощённое практическое правило:
z-index применяется к позиционированным элементам (у которых position не static).
Также z-index применяется к flex- и grid-элементам, даже если они не позиционированы.Это означает, что z-index: 10 на обычном блочном элементе в потоке может не дать эффекта, если элемент не участвует в нужном контексте.
Stacking context: почему z-index «не пробивает» наружу
Самая частая ловушка: вы поставили z-index: 9999, а элемент всё равно под чем-то.
Причина часто в том, что родитель создал свой контекст наложения, и z-index детей сравнивается только внутри этого контекста.
Распространённые причины появления нового stacking context (практически важные):
position (не static) вместе с z-index (не auto).
transform со значением отличным от none.
opacity меньше 1.!Почему большой z-index не всегда перекрывает соседний блок
Практический паттерн: выпадающее меню поверх шапки
На шапке задаём слой.
На меню задаём слой выше внутри того же контекста.Важно: если вы задаёте z-index на разных «ветках» DOM, сначала убедитесь, что они сравниваются в одном контексте наложения.
Как выбирать инструмент: поток, Flex/Grid или position
Чтобы вёрстка была устойчивой и соответствовала архитектуре из прошлых уроков:
Используйте нормальный поток для базового вертикального построения страницы.
Используйте Flexbox для выравнивания элементов в строке/колонке и управления расстояниями через gap.
Используйте Grid для сеток секций, карточек и двухмерных раскладок.
Используйте position для локальных задач перекрытия и «прилипания», а не для построения основного макета.Полезный тест: если вы начинаете собирать целую секцию на absolute, скорее всего вы пытаетесь компенсировать плохую структуру, неудачные размеры или неправильную раскладку.
Мини-чеклист отладки position и z-index
Элемент должен смещаться, но не смещается.
- Проверьте, что
position не
static.
- Проверьте, что вы задали
top/right/bottom/left.
absolute позиционируется «от страницы», а не от блока.
- Проверьте ближайшего предка с
position не
static.
sticky не липнет.
- Проверьте
top.
- Проверьте, есть ли прокрутка.
- Проверьте
overflow у предков.
z-index не работает.
- Проверьте, участвует ли элемент в слоёвом контексте.
- Найдите, не создаёт ли родитель отдельный stacking context.
Связь с архитектурой страницы и компонентами
Позиционирование становится предсказуемым, если у вас:
есть понятные контейнеры компонентов (например, .card), на которые можно поставить position: relative как якорь;
отступы и размеры контролируются через блочную модель и gap, а не через хаотичные сдвиги;
крупная раскладка делается Flexbox/Grid, а position оставлен для точечных «слоёв».В следующих материалах мы будем применять эти правила к типовым компонентам: выпадающим меню, модальным окнам и сложным секциям, где важно не перепутать раскладку сетками и позиционирование.