Как на самом деле работает position: sticky в CSS
![]()
У position: sticky уже очень неплохая браузерная поддержка, но большинство разработчиков так и не используют это свойство.
У этого есть две основные причины: во-первых, браузерам потребовалось много времени на реализацию адекватной поддержки этого свойства. И все просто успели забыть о нём.
Во-вторых, многие разработчики до конца не понимают логику, по которой это свойство работает. И тут появляюсь я!
Я полагаю, что вы хорошо знакомы с позиционированием в CSS, но давайте кратко повторим основные моменты:
Ещё три года назад существовало четыре типа позиционирования: static , relative , absolute и fixed .
Основное различие между static и relative , absolute и fixed в том, какое место они занимают в потоке документа (DOM). Элементы с позицией static и relative сохраняют своё естественное положение в потоке документа, в то время как absolute и fixed «вырываются» из потока документа и становятся плавающими.
Новое значение sticky похоже на все предыдущие значения сразу. Я проиллюстрирую это чуть позже.
Моё первое знакомство с «липким» позиционированием
Думаю, что большинство из вас игрались с «липким» позиционированием. Так было и у меня, пока в один момент я не осознал, что совсем не понимаю это свойство.
При первом знакомстве с position: sticky все быстро понимают, что элемент залипает, когда область просмотра достигает определённой позиции.
Проблема в том, что иногда это работает, а иногда нет. Когда всё работает, то элемент и правда залипает. Но когда не работает, то при прокрутке элемент перестаёт залипать. Как человеку, который живёт одним только CSS, мне было важно разобраться в сути проблемы. Именно поэтому я решил тщательно изучить «липкое» позиционирование.
«Липкая» разведка
Во время своих экспериментов я заметил, что если элемент с position: sticky является единственным ребёнком своего родителя-обёртки, то этот «липкий» элемент не залипает.
Когда я добавлял больше элементов внутрь родителя-обёртки всё начинало работать как ожидалось.
Почему так происходит?
Причина кроется в том, что элемент с position: sticky может перемещаться только в пределах контейнера, в котором находится. А поскольку в моём случае он был единственным ребёнком, у него не было элементов-братьев, поверх которых он мог перемещаться.
Как на самом деле работает position: sticky в CSS
«Липкое» позиционирование состоит из двух основных частей: «липкого» элемента и «липкого» контейнера.
«Липкий» элемент — это элемент, которому мы задали position: sticky . Элемент будет становиться плавающим, как только область видимости достигнет определённой позиции, например top: 0px .
«Липкий» контейнер — это HTML-элемент, который оборачивает «липкий» элемент. Это максимальная область, в которой может перемещаться наш элемент.
Когда вы задаёте элементу position: sticky , его родитель автоматически становится «липким» контейнером!
Очень важно это запомнить! Контейнер будет являться областью видимости для элемента. «Липкий» элемент не может выйти за пределы своего «липкого» контейнера.
В этом причина, почему в предыдущем примере «липкий» элемент не залипал: он был единственным дочерним элементом контейнера.
Понимание «липкого» поведения
Как я и говорил, position: sticky ведёт себя не так, как другие типы позиционирования. Но, с другой стороны, у них есть определённые сходства. Позвольте мне пояснить:
Относительное (или статичное) — «липкий» элемент похож на элемент со статическим или относительным позиционированием поскольку сохраняет свою естественную позицию в DOM (остаётся в потоке).
Фиксированное—когда элемент залипает, то ведёт себя как будто у него заданы стили position: fixed , остаётся на той же позиции в области видимости и вырывается из потока документа.
Абсолютное—в конце доступной для перемещений области элемент останавливается и остаётся поверх другого элемента. Точно также, как ведёт себя абсолютно спозиционированный элемент в контейнере с position: relative .
Залипает внизу?!
В большинстве случаев вы будете использовать position: sticky чтобы прикрепить элемент к верхнему краю страницы. Что-то вроде этого:
Именно для таких сценариев и был создан этот тип позиционирования. До его появления такой трюк приходилось проворачивать с помощью JavaScript.
Но вы с тем же успехом можете использовать это свойство для того, чтобы прилепить элемент к нижней границе. Это значит, что футеру можно задать «липкое» позиционирование и при скролле он всегда будет залипать у нижнего края. И когда мы дойдём до конца «липкого» контейнера наш элемент остановится на своей естественной позиции. Лучше использовать эту особенность для элементов, находящихся в самом конце контейнера.
В реальной жизни я использую такое поведение для сводных таблиц. И, я думаю, с помощью этого приёма можно реализовать «липкую» навигацию в футере.
Браузерная поддержка
- «Липкое» позиционирование поддерживается всеми основными современными браузерами. Исключение: старый-добрый IE.
- Для Safari потребуется префикс -webkit
В заключении
Вот и всё. Я надеюсь, что вам понравилась эта статья и мне удалось поделиться своим опытом. Я буду признателен, если вы поделитесь этим постом и поаплодируйте.
How to Use CSS Position Sticky

Want to learn how to use the CSS position: sticky property?

In CSS, there are hundreds of properties that enable you to control the look and feel of your web page. One of the most commonly used is the CSS position property, which allows you to position page elements. Whether you’re building your site from scratch or using a framework like Bootstrap CSS, this property can make your life as a developer a lot easier.
CSS position: sticky — создание эффектов пролистывания с использованием липкого позиционирования

Липкие элементы (CSS position sticky;) очень похожи на фиксированные (position: fixed;), поскольку они сохраняют свое положение на экране, даже когда пользователь прокручивается страницу вверх или вниз. В чем разница? Липкий элемент остается ограниченным родительским контейнером, в котором он находится. Сравните пример выше с этим, в котором используется та же концепция, но через фиксированный элемент:

Профессия Frontend-разработчик PRO
Готовим Frontend-разработчиков с нуля
На курсе вы научитесь создавать интерфейсы веб-сервисов с помощью языков программирования и дополнительных технологий. Сможете разрабатывать планировщики задач, мессенджеры, интернет-магазины…
Предположим, мы хотим создать эффект, когда элементы пролистываются или скрываются при прокрутке — вроде как эффект параллакса. Например, заголовок и футер, который скрываются и показываются при прокрутке:
И угадайте что? Мы можем сделать это с помощью липких элементов!
Как мы это сделали? Рад, что вы спросили. Давайте выясним.
Настройка HTML
В нашем примере есть три липких элемента:
Первый — заголовок категории, который уходит под тело статьи, когда достигает вершины экрана.
Второй — название статьи, и оно остается видимым в верхней части экрана, а контент статьи исчезает под ним при прокрутке (что является типичным поведением липкого элемента).
Третий элемент — футер, который уходит под тело статьи и появляется, когда статья прокручивается выше определенного порога.
Давайте посмотрим, как это делается. Вот HTML, с которым мы работаем … в основном два блока article:
Липкий CSS
Элементы .category, .title и .footer получат position:sticky; вместе со свойством позиционирования, указывающим, в какой части экрана они начнут «прилипать» при прокрутке.
Я не настраиваю значительно липкие элементы, только задаю некоторые стили. Они и так уже делают то, что им нужно делать: закрепляются на экране. Осталось только создать перекрытие и некоторое пространство между краем страницы и прокручиваемыми элементами.
Вероятно, есть огромное количество способов, с помощью которых мы можем создать перекрытие, с помощью которого будут скрываться элементы — я выбрал фоновое изображение.
К статье применяется линейный градиент фона, который идет сверху вниз, начиная с 50px, где фон полностью прозрачный, затем он резко переходит в цветной и на 50px снизу снова прозрачный. Это работа для calc? Таким образом у нас есть две прозрачные полосы размером 50 пикселей, одна сверху и одна внизу, с равной высотой, соответствующей высоте заголовка категории и футера.

Заголовок категории и футер статьи — это элементы, которые уходят под текст и выходят из-под него, поэтому их высоты определяют, как долго прозрачные полосы будут находиться вверху и внизу градиента.
Чтобы реализовать это, заголовок категории и заголовок статьи прикрепляются к экрану, когда их вершины выравниваются с вершиной окна просмотра. Название статьи укладывается поверх заголовка категории и, когда оно достигает верхней части окна просмотра, полностью скрывает заголовок категории.
Что касается футера, он останавливается на 100 пикселей выше нижней части экрана (внутри границы статьи), но вы не увидите его, так как он скрывается под содержимым с помощью z-index: -1. Он будет виден, как только мы прокрутим начало последней прозрачной полосы фона статьи.
Поскольку заголовок категории не содержит ничего, что нужно скрывать, кроме самого текста, неплохо задать для последнего липкого элемента (футера) отступ сверху 50 пикселей (чтобы все было равномерным), чтобы вы его не увидели за заголовком категории при прокрутке. Вот и все!
Теперь, конечно, вы захотите сделать это самостоятельно и изменить, например, размеры, количество элементов и тип контента. Главное — создать те перекрытия, которые позволяют вашим липким элементам скрываться и проявляться по мере их прокрутки — опять-таки, есть разные способы сделать это, но я выбрал прозрачные полосы в градиенте.
Есть другой пример? Конечно!
Вот еще один пример с горизонтальной прокруткой (и горизонтальным градиентом), который может быть идеальным для применения этой концепции на мобильных устройствах:
Посмотрите, как появляются фрукты, когда одна статья выходит из окна просмотра, и скрываются, когда следующая статья накладываются на них? Такая же настройка HTML:
Я собираюсь перейти к решению линейного градиента для создания перекрытий, на этот раз идущих слева направо, чтобы учесть горизонтальную прокрутку:
Отметим еще раз, что мы собираемся использовать те же две прозрачных полосы в 50 пикселей, что и раньше, с той лишь разницей, что мы применяем их по ширине, а не по высоте.
Оба липких элемента (название и изображение) будут уходить под статью. Таким образом, чтобы избежать перекрытия их во время прокрутки, для заголовка нужно задать соответствующий отступ, равный ширине изображения — 50 пикселей (плюс дополнительные 2 пикселя для более чистой линии в Chrome).
Вот что происходит: когда мы прокручиваем страницу по горизонтали, заголовок останавливается в 20 пикселях от левого края экрана, а изображение — в 150 пикселях. Поскольку они оба имеют z-index: -1;, они скрываются под статьей (фоновым градиентом) — они скрыты, когда они находятся под областью со сплошным цветом, и появляются под прозрачными полосками.
ОК, еще один пример
Прежде чем закончить, позвольте мне показать вам еще один пример, который вдохновил этот пост. Это футер сайта, который показывается при прокрутке. Я впервые увидел этот дизайн на веб-сайте Райана Седдона давным-давно.
Этот дизайн обычно создается с помощью «фиксированного» футера, которому отведено некоторое пространство в конце страницы. Я думал, что если фиксированные элементы могут сделать это для всей страницы, то, возможно, липкие элементы могут сделать что-то похожее для отдельных элементов — и, следовательно, мы можем получить то, что рассматривали до сих пор.
Следовательно, мы можем осуществить тот же эффект, используя липкие методы. Во-первых, HTML: