Menu

Position в CSS: absolute, relative, fixed и sticky

position: absolute размещает элемент по точным координатам внутри ближайшего позиционированного предка. Разберем, как absolute работает вместе с position: relative, затем fixed и sticky, свойства top/right/bottom/left и inset и почему sticky иногда не прилипает.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

position: absolute на одном примере

Абсолютно позиционированный элемент извлекается из обычного потока и размещается через top, right, bottom и left. Эти смещения отсчитываются от ближайшего предка, у которого position не static, поэтому родителю задают position: relative:

Удалите position: relative у .card, и бейдж прыгнет в правый верхний угол всей страницы, потому что у него больше нет позиционированного предка. Эта одна строка объясняет большинство вопросов «не работает position absolute».

Что нужно знать об абсолютных элементах:

  • Они не занимают места. Заголовок и абзац размещены так, будто бейджа нет.
  • Их ширина сжимается по содержимому, если не задать width или сразу left и right.
  • Смещения отсчитываются от края padding содержащего блока, внутри его рамки.

Пять значений position

ЗначениеВ потоке?Смещения отсчитываются отТипичное применение
static (по умолчанию)ДаСмещения игнорируютсяОбычные элементы
relativeДа, место сохраняетсяСобственного обычного положенияОпора для абсолютных дочерних элементов, небольшие сдвиги
absoluteНетБлижайшего позиционированного предка (или страницы)Бейджи, подсказки, наложения, кнопки закрытия
fixedНетОкна просмотраШапки, кнопки чата, плашки cookie
stickyДаКонтейнера прокрутки, когда элемент доходит до смещенияЗаголовки таблиц, заголовки разделов, боковые панели

position: relative

Относительно позиционированный элемент остается на своем месте в потоке. Смещения меняют место, где он рисуется, но его исходное место остается зарезервированным, поэтому ничего вокруг не сдвигается:

Блок 2 нарисован на 20px ниже и на 20px правее и перекрывает блок 3, но блок 3 не сдвинулся: он по-прежнему оставляет место для блока 2 в исходной позиции. Сам по себе relative редко используют для перемещения; его главная задача быть опорным блоком для абсолютных дочерних элементов.

Смещения и inset

top, right, bottom и left принимают длины, проценты (от содержащего блока) и auto. Сокращенное свойство inset задает все четыре в том же порядке, что и margin:

.overlay {
  position: absolute;
  inset: 0;              /* top: 0; right: 0; bottom: 0; left: 0; */
}
.corner {
  position: absolute;
  inset: auto 16px 16px auto;  /* bottom right corner, 16px in */
}

Если задать противоположные стороны, элемент растягивается: left: 0; right: 0 делает его шириной с содержащий блок. inset: 0 у абсолютного дочернего элемента это стандартный способ накрыть карточку наложением.

Центрирование через absolute и transform

top: 50%; left: 50% ставит левый верхний угол элемента в центр. translate(-50%, -50%) затем сдвигает его назад на половину собственного размера:

Flexbox и grid центрируют проще, если элемент может оставаться в потоке; все способы сравниваются на странице выравнивание div по центру.

position: fixed

Фиксированный элемент размещается относительно окна просмотра и остается на месте при прокрутке страницы:

.chat-button {
  position: fixed;
  bottom: 16px;
  right: 16px;
}

Два подвоха. Фиксированный элемент не занимает места, поэтому фиксированная шапка закрывает верх страницы, если не добавить body padding-top. А если у любого предка есть transform, filter или perspective, опорным блоком становится этот предок, а не окно просмотра, и элемент прокручивается вместе с ним.

position: sticky

Липкий элемент прокручивается как обычно, пока не дойдет до своего смещения, а затем прилипает там, пока конец его родителя не уйдет за край. Прокрутите блок ниже:

Каждая буква прилипает к верху блока прокрутки, пока виден ее раздел, а затем ее выталкивает следующая, потому что липкий элемент никогда не покидает своего родителя.

Если sticky не прилипает, проверьте:

  • Нет смещения. position: sticky ничего не делает без top, bottom, left или right.
  • Предок с overflow: hidden, auto или scroll. Он становится контейнером прокрутки, и если он на самом деле не прокручивается, ничего не прилипает. Используйте overflow: clip, если нужно только скрыть переполнение.
  • Родитель не выше липкого элемента. Внутри него негде прилипать.
  • Flex- или grid-родитель растягивает его. Во flex-строке добавьте липкой боковой панели align-self: flex-start.

Частые ошибки

  • Забытый position: relative у родителя абсолютного элемента.
  • Absolute для раскладки страницы. Абсолютные элементы игнорируют друг друга и содержимое, поэтому на маленьких экранах текст наезжает. Для раскладки используйте flexbox или grid, а absolute для небольших украшений.
  • Смещения у статичного элемента. top: 10px ничего не делает без position.
  • Споры о том, какой элемент сверху. Порядок перекрывающихся позиционированных элементов задает z-index.
  • Фиксированная шапка скрывает содержимое. Добавьте странице padding или scroll-padding-top, чтобы ссылки-якоря не прятались под шапкой.

Часто задаваемые вопросы

Что делает position: absolute?

Убирает элемент из обычного потока (остальные элементы ведут себя так, будто его нет) и размещает его через top, right, bottom и left, отсчитывая от содержащего блока: ближайшего предка, у которого position не static.

Как спозиционировать элемент абсолютно относительно родителя?

Задайте родителю position: relative;, а дочернему элементу position: absolute; со смещениями вроде top: 0; right: 0;. Без позиционированного родителя дочерний элемент размещается относительно страницы.

Чем position relative отличается от absolute?

relative оставляет элемент в потоке и только сдвигает место, где он рисуется, сохраняя его исходное место. absolute убирает его из потока и размещает относительно позиционированного предка.

Почему не работает position: sticky?

Обычно по одной из трех причин: не задан top (или другое смещение), у предка overflow: hidden или auto, и он становится контейнером прокрутки, или родитель липкого элемента не выше самого элемента, так что прилипать негде.

Чем fixed отличается от sticky?

fixed убирается из потока и закрепляется относительно окна просмотра (если только у предка нет transform или filter). sticky остается в потоке и прокручивается как обычно, пока не дойдет до своего смещения, а затем прилипает, пока его родитель еще на экране.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ