Липкое позиционирование: position sticky

position: sticky - гибрид relative и fixed: элемент ведёт себя как обычный, пока страница (или контейнер) не прокрутится до заданного порога, а затем "прилипает" к краю и остаётся на месте, пока не закончится место внутри родителя. Без явного top/right/bottom/left sticky не отличить от обычного relative.

Попробуй прямо сейчас: прокрути список внутри блокнота - заголовок "приклеится" к верхней границе именно этого прокручиваемого блока, а не ко всему экрану.

Гибрид relative и fixed: как работает порог прилипания

sticky-элемент ведёт себя как обычный position: relative, оставаясь в потоке документа, пока не будет достигнут заданный порог прокрутки - например, top: 10px означает "веди себя как relative, пока до верхней границы контейнера прокрутки не останется 10px". После этого элемент "прилипает" - визуально ведёт себя как fixed, но только внутри границ своего родителя, а как только родитель заканчивается (прокрутка дошла до его нижнего края), sticky-элемент снова уходит в обычный поток вместе с родителем.

position: sticky; top: 0; - классический "липкий" заголовок списка или таблицы, который останавливается у верхнего края при прокрутке.

position: sticky; без top/left и подобных, ожидая прилипание "по умолчанию" - без заданного порога sticky ничем не отличается от обычного relative.

Без offset sticky не работает вообще

Ключевое правило: sticky ОБЯЗАТЕЛЬНО нужен хотя бы один из top, right, bottom или left, задающий сам порог прилипания. Без него браузеру не от чего отталкиваться, и элемент просто останется обычным relative - визуально прилипания не будет вообще, даже если написать position: sticky.

position: sticky; bottom: 0; - элемент прилипнет к нижнему краю контейнера при прокрутке вниз.

position: sticky; без единого offset - самая частая причина, по которой "sticky не работает": свойство написано верно, но порог не задан вовсе.

Прокручиваемый предок и почему sticky "ломается"

sticky прилипает не ко всей странице, а к своему БЛИЖАЙШЕМУ ПРОКРУЧИВАЕМОМУ ПРЕДКУ - границы прилипания задаёт именно он. По спецификации "механизм прокрутки" создаёт любой предок с overflow: hidden, scroll, auto или overlay - причём даже если сам этот предок фактически не прокручивается. Это самая частая причина, когда sticky "не работает": где-то в цепочке предков случайно оказался overflow, отличный от visible - об этой же проблеме, только со стороны overflow, уже говорилось в уроке про overflow. Ещё две частые причины: у родителя sticky-элемента задана высота auto вместо явного значения (прилипать физически некуда без известных границ), или сам sticky-элемент по размеру больше, чем родитель.

.list-wrap { overflow-y: auto; height: 300px; } с явной высотой - предсказуемый контейнер, внутри которого sticky будет работать корректно.

.wrapper { overflow: hidden; } где-то выше по дереву предков, случайно (например, для обрезки декоративного элемента) - это создаёт "механизм прокрутки", который может испортить прилипание sticky-элемента внутри.

Из истории position:sticky - редкий случай CSS-свойства, которое реализовали, затем ПОЛНОСТЬЮ УБРАЛИ из браузера и лишь спустя годы вернули обратно. Впервые sticky появился в WebKit (тогдашнем движке Chrome) примерно в 2012 году, но уже через год разработчики Chrome убрали его, объяснив это тем, что тогдашняя реализация плохо сочеталась с системой прокрутки и композитинга браузера. Баг по новой реализации оставался открытым с 2013 года, и sticky вернулся только в Chrome 56 - в бета-версии в декабре 2016-го и в стабильном релизе в январе 2017-го. Между "изобретением" и надёжной постоянной поддержкой прошло около пяти лет, причём с полным перерывом посередине - случай необычный даже по меркам CSS, где свойства обычно просто медленно добирают поддержку, а не исчезают и не возвращаются.

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Забывают задать top/right/bottom/left sticky ведёт себя как обычный relative, никакого прилипания Всегда задавать хотя бы один порог (чаще всего top)
У одного из предков случайно overflow ≠ visible sticky перестаёт прилипать как задумано - предок создал "механизм прокрутки" Проверять всю цепочку предков на overflow: hidden/scroll/auto/overlay
У родителя sticky-элемента высота auto Прилипать физически некуда - границы родителя неизвестны заранее Задать родителю явную высоту
Ждут прилипания ко всей странице, а не к ближайшему прокручиваемому контейнеру Элемент прилипает к границе своего родителя-контейнера с прокруткой, а не ко всему окну Проверять, какой именно предок на самом деле прокручивается

Шпаргалка

Что нужноКак сделать
Липкий заголовок списка/таблицыposition: sticky; top: 0;
Обязательное условие для работы stickyхотя бы один из top/right/bottom/left
Где sticky "прилипает"к ближайшему прокручиваемому предку, не обязательно ко всей странице
Частая причина поломкиoverflow ≠ visible у одного из предков
Ещё одна причина поломкиheight: auto у родителя sticky-элемента

Коротко: отвечаем на вопросы

Почему мой position: sticky не прилипает?

Чаще всего причина одна из трёх: не задан ни один offset (top/right/bottom/left); у одного из предков случайно overflow: hidden, scroll или auto, что создаёт мешающий "механизм прокрутки"; или у родителя sticky-элемента высота auto, из-за чего границы для прилипания неизвестны заранее.

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

fixed всегда привязан к окну просмотра целиком и не зависит от родителя. sticky ведёт себя как relative, пока не достигнут порог прокрутки, а затем прилипает только внутри границ своего ближайшего прокручиваемого родителя - и снова "отклеивается", когда родитель заканчивается.

К чему прилипает sticky-элемент - ко всей странице?

Не обязательно. sticky прилипает к своему ближайшему прокручиваемому предку - это может быть как вся страница, так и отдельный блок с overflow: auto/scroll, если он находится ближе в дереве предков.

Категория
css
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×