position: fixed привязывает элемент к окну просмотра целиком - при прокрутке страницы он остаётся на одном и том же месте экрана, будто приклеенный. Как и у absolute, место в потоке не резервируется, а размер по умолчанию - по содержимому.
В этом уроке
Попробуй прямо сейчас: прокрути блок с рамкой внутри блокнота — кнопка "Наверх" останется в том же углу, хотя содержимое блока уедет вверх.
Привязка к окну просмотра: что происходит при прокрутке
fixed отсчитывает top/right/bottom/left от краёв окна просмотра (viewport), а не от какого-либо блока в разметке - в этом его ключевое отличие от absolute. При прокрутке страницы координаты fixed-элемента на экране не меняются вообще: он не "уезжает" вместе с контентом, а остаётся точно на том же месте. Это же поведение приводило к болезненной истории на мобильных устройствах - в обзорном уроке про position уже рассказывалось, что десктопный IE5.5/6 вообще не поддерживал fixed, но и после того, как эта проблема решилась, на мобильных всё повторилось заново с большими багами.
position: fixed; bottom: 20px; right: 20px; - классическая кнопка "наверх", которая всегда на виду, независимо от прокрутки.
position: absolute; bottom: 20px; right: 20px;, ожидая, что кнопка останется на экране при прокрутке - absolute отсчитывается не от viewport, а от ближайшего позиционированного предка (или страницы), и при прокрутке "уедет" вместе с контентом.
Исключение: transform, filter и perspective у предка
Как и у absolute из прошлого урока, здесь есть то же самое исключение: если у ЛЮБОГО предка fixed-элемента задан transform, filter или perspective, отличный от none, - точкой отсчёта становится именно ЭТОТ предок, а не окно просмотра. Это работает, даже если у самого предка position: static - в этом случае fixed фактически ведёт себя как absolute внутри такого предка. Такая ситуация - частая и неожиданная причина того, что "прилипший" элемент вдруг перестаёт быть прилипшим и начинает уезжать вместе со страницей.
position: fixed; у элемента вне блоков с анимациями/transform - предсказуемо привязан к окну просмотра.
.page-wrapper { transform: translateZ(0); } на всей странице (частый приём для аппаратного ускорения анимаций) с вложенным fixed-элементом внутри - fixed внутри такого wrapper'а перестанет быть привязанным к экрану и станет вести себя как absolute внутри wrapper'а.
Размер по умолчанию и место в потоке
Без явных width и height fixed-элемент, как и absolute, занимает размер по своему содержимому, а не растягивается на весь экран или родителя. Место в потоке документа тоже не резервируется - соседние элементы ведут себя так, будто fixed-элемента вообще не существует в разметке.
position: fixed; width: 100%; - явно растянуть на всю ширину, например, для фиксированной шапки сайта.
position: fixed; без width, ожидая шапку на всю ширину экрана - без явного width элемент останется по размеру содержимого, а не растянется на весь экран.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Используют absolute вместо fixed для элементов, которые должны оставаться на экране | Элемент "уезжает" вместе со страницей при прокрутке, а не остаётся на месте | Использовать position: fixed, если элемент должен быть привязан именно к окну просмотра |
| Не подозревают, что transform/filter у предка "ломает" fixed | fixed-элемент вдруг начинает вести себя как absolute и уезжать при прокрутке | Проверять предков на transform/filter/perspective, если fixed перестал "прилипать" к экрану |
| Ждут, что fixed-элемент без width растянется на весь экран | Элемент остаётся по размеру содержимого, а не занимает всю ширину | Задать width явно (например, width: 100% для шапки на всю ширину) |
Шпаргалка
| Что нужно | Как сделать |
|---|---|
| Кнопка "наверх" на весь экран | position: fixed; bottom: 20px; right: 20px; |
| Фиксированная шапка на всю ширину | position: fixed; top: 0; left: 0; width: 100%; |
| Случайно "ломает" fixed у потомков | transform/filter/perspective ≠ none у любого предка |
| Размер fixed-элемента без width/height | по содержимому, не растягивается |
| Место в потоке документа | не резервируется, как у absolute |
Коротко: отвечаем на вопросы
Уезжает ли fixed-элемент вместе со страницей при прокрутке?
Нет - в этом и есть смысл position: fixed. Он привязан к окну просмотра (viewport), а не к контенту страницы, поэтому остаётся на одном и том же месте экрана независимо от прокрутки. Если элемент всё же "уезжает", скорее всего у одного из его предков задан transform, filter или perspective.
Почему мой fixed-элемент вдруг перестал прилипать к экрану?
Скорее всего, у одного из предков этого элемента задан transform, filter или perspective, отличный от none - даже без position такой предок становится точкой отсчёта для fixed-потомка вместо окна просмотра, и элемент начинает вести себя как absolute.
Чем fixed отличается от absolute на практике?
Оба ведут себя одинаково по большинству правил (не резервируют место, размер по содержимому), но точка отсчёта разная: absolute отсчитывается от ближайшего позиционированного предка, а fixed - от окна просмотра целиком, и поэтому не двигается при прокрутке страницы.