Перейти к содержанию
Innovialabs

CSS position: static, relative, absolute, fixed и sticky

Основы4 мин

Коротко

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 не прилипает

Пройдитесь по списку:

  1. Не задан порог. Без top (или bottom) sticky ведёт себя как relative.
  2. У предка есть overflow: hidden, auto или scroll. Sticky прилипает к ближайшему прокручиваемому предку, а не к окну. Если этот предок сам не прокручивается, эффекта не будет.
  3. Родитель не выше самого элемента. Sticky двигается только внутри родителя. Если родитель по высоте равен элементу, прилипать некуда.
  4. Элемент во flex-контейнере растянут. В ряду flex элементы по умолчанию растягиваются на всю высоту. Помогает align-self: flex-start.

Почему absolute «прыгает»

  • У родителя нет position: relative — координаты считаются от более дальнего предка или страницы.
  • Не заданы top/left — элемент остаётся там, где был бы в потоке, и сдвигается вместе с соседним контентом.
  • Проценты считаются от размеров containing block, а не от самого элемента. Для центрирования используйте inset: 0; margin: auto с заданными размерами или transform: translate(-50%, -50%).

Частые вопросы

relative остаётся в потоке и сдвигается от своего места, не затрагивая соседей. absolute выходит из потока, соседи занимают его место, а координаты считаются от позиционированного предка.

Поможем с этим

Если хотите не разбираться самим, а получить результат — этим мы занимаемся каждый день.

Обсудить проект

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.