CSS position: static, relative, absolute, fixed и sticky
Основы4 минРедакция Innovialabs
Коротко
static — обычный поток, relative сдвигает элемент и сохраняет место, absolute и fixed вынимают его из потока и считают координаты от позиционированного предка или окна, а sticky прилипает при прокрутке внутри своего родителя.
Короткий ответ
Свойство position решает две вещи: остаётся ли элемент в обычном потоке и от чего считаются top, right, bottom, left.
| Значение | В потоке? | Координаты считаются от | Типичное применение |
|---|---|---|---|
static | Да | Не работают | Всё по умолчанию |
relative | Да, место сохраняется | Своего обычного положения | Небольшой сдвиг, опора для absolute |
absolute | Нет | Ближайшего позиционированного предка | Бейдж на карточке, выпадающее меню |
fixed | Нет | Окна браузера | Шапка, кнопка «наверх», чат-виджет |
sticky | Да | Ведёт себя как relative, пока не достигнет порога | Липкая шапка таблицы, боковое меню |
Каждое значение на примере
static. Элементы идут друг за другом, как текст в документе. top и z-index на такой элемент не действуют.
relative. Элемент сдвигается визуально, но его исходное место остаётся пустым — соседи не двигаются.
.note { position: relative; top: 8px; left: 8px; }
Главная практическая польза relative — сделать элемент опорой для абсолютно позиционированных детей.
absolute. Элемент вынимается из потока: соседи смыкаются, будто его нет. Координаты считаются от ближайшего предка, у которого position не static.
.card { position: relative; }
.card .badge { position: absolute; top: 12px; right: 12px; }
fixed. Элемент прикрепляется к окну и не двигается при прокрутке. Под ним остаётся контент, поэтому у фиксированной шапки нужно компенсировать высоту отступом.
sticky. Гибрид: элемент в потоке, пока не дойдёт до порога (например, top: 0), а потом прилипает — но только в пределах своего родителя.
.table-head { position: sticky; top: 0; }
Containing block: от чего считаются координаты
Containing block — прямоугольник, относительно которого считаются координаты и проценты.
- Для
absolute— ближайший предок сpositionнеstatic. Если такого нет — начальный блок страницы, и элемент «улетает» в угол документа. - Для
fixed— окно браузера. Но если у любого предка естьtransform,filterилиperspective,fixedначинает считаться от этого предка и перестаёт быть фиксированным при прокрутке. - Те же свойства (
transform,filter) делают предка опорой и дляabsolute.
z-index и stacking context
z-index управляет порядком наложения, но работает только у позиционированных элементов (а также у flex- и grid-элементов).
Главное, что нужно понимать, — stacking context. Это «слой», внутри которого z-index сравниваются только между собой. Новый контекст создают, например:
position: relative/absoluteвместе сz-index, отличным отauto;position: fixedиsticky;opacityменьше 1,transform,filter;isolation: isolate.
Поэтому модальное окно с z-index: 9999 может оказаться под шапкой: если оно лежит внутри родителя со своим контекстом и z-index: 1, а у шапки z-index: 2, ребёнок не может выбраться выше своего родителя. Лечится переносом модалки ближе к корню документа или правкой z-index у родителей, а не увеличением числа.
Почему sticky не прилипает
Пройдитесь по списку:
- Не задан порог. Без
top(илиbottom) sticky ведёт себя как relative. - У предка есть
overflow: hidden,autoилиscroll. Sticky прилипает к ближайшему прокручиваемому предку, а не к окну. Если этот предок сам не прокручивается, эффекта не будет. - Родитель не выше самого элемента. Sticky двигается только внутри родителя. Если родитель по высоте равен элементу, прилипать некуда.
- Элемент во flex-контейнере растянут. В ряду flex элементы по умолчанию растягиваются на всю высоту. Помогает
align-self: flex-start.
Почему absolute «прыгает»
- У родителя нет
position: relative— координаты считаются от более дальнего предка или страницы. - Не заданы
top/left— элемент остаётся там, где был бы в потоке, и сдвигается вместе с соседним контентом. - Проценты считаются от размеров containing block, а не от самого элемента. Для центрирования используйте
inset: 0; margin: autoс заданными размерами илиtransform: translate(-50%, -50%).