Почему не работает position sticky
Перейти к содержимому

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

  • автор:

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

Несмотря на то, что на этом сайте сайдбар у меня так и фиксируется при помощи JavaScript, но на многих других проектах я уже давно перешёл на свойство CSS position:sticky . Ребят, мне оно очень нравится!

Тем не менее неоднократно у меня случались ситуации, что на некоторых проектах я тратил довольно большое количество времени, чтобы заставить его работать.

Поэтому в этом уроке мы разберём все возможные ситуации, в которых оно может не срабатывать. Такой своебразный чеклист, по которому можно пройтись.

1. Проверим поддержку браузером

Ладно, это слишком банально. Но на опыте научен, что никогда не нужно рассчитывать, что вещи, очевидные для тебя, будут также очевидны для 100% всех других людей. Такого не произойдёт.

Поэтому в первую очередь переходим на сайт caniuse и проверяем, входит ли ваш браузер в поддержку.

2. Убедитесь, что задано позиционирование

Тут нужно убедиться, что помимо того, что вы дописали элементу position:sticky , вам также нужно задать один из следующих параметров:

Дело заключается в том, что когда ни один из них не задан, это значит, что они все равны auto , в таком случае не ждите, что position:sticky заработает у вас.

То есть например:

.true-sidebar{ position: sticky; top: 10px; }

3. В Safari может понадобиться префикс

Если вы используете Safari и его версия ниже, чем 13, то вам понадобится добавить префикс -webkit .

поддержка position:sticky в старых версиях Safari

В коде это будет:

.true-sidebar{ position: -webkit-sticky; position: sticky; top: 10px; }

4. Проверим overflow у родительского элемента

Если у родительского элемента (на любом уровне) задано свойство overflow и выставлено в одно из следующих значений:

  • overflow: hidden
  • overflow: scroll
  • overflow: auto

То это может стать проблемкой.

Чтобы слишком не страдать, вы можете воспользоваться сниппетом JavaScript, который быстро проверит всех родителей:

let parent = document.querySelector( '.true-sidebar' ).parentElement; while (parent) { const hasOverflow = getComputedStyle(parent).overflow; if( 'visible' !== hasOverflow) { console.log( hasOverflow, parent ); } parent = parent.parentElement; }

Но там можно поиграться со свойством height и всё заработает.

5. А какая вообще высота у первого родительского элемента?

Тут на самом деле прикол, если у вас есть какой-то элемент, скажем .true-wrapper , и у него не задана никакая высота, то эта высота вполне возможно будет совпадать с высотой .true-sidebar и что по итогу? Нашему сайдбару просто негде будет скроллиться.

В таких ситуациях помогает даже код:

.true-wrapper{ height: 100%; }

6. А не на флексах ли написан родительский элемент?

Когда у родительского элемента стоит свойство display:flex , то это может создать проблемки в двух ситуациях:

  • align-self: auto стоит у нашего сайдбара (а это по умолчанию вообще-то),
  • align-self: stretch .

Если не вдаваться в слишком подробности, то наш сайдбар растянется на весь размер родительского элемента и у него не останется свободного места для скролла.

Решение совсем не трудное – выставить align-self: flex-start . Ниже собрал для вас весь код:

.true-wrapper{ display:flex; height: 100%; } .true-sidebar{ position: -webkit-sticky; position: sticky; top: 10px; align-self: flex-start; }

Миша

Впервые познакомился с WordPress в 2009 году. Организатор и спикер на конференциях WordCamp. Преподаватель в школе Нетология.

Пишите, если нужна помощь с сайтом или разработка с нуля.

position : sticky

Уникальное позиционирование, которое создаёт липкий элемент.

Время чтения: меньше 5 мин

Открыть/закрыть навигацию по статье
Контрибьюторы:

Обновлено 8 мая 2023

Кратко

Скопировать ссылку «Кратко» Скопировано

Элемент с position : sticky «прилипает» к экрану при прокрутке, пока не встретится с границей родительского блока.

Пример

Скопировать ссылку «Пример» Скопировано

Сделаем «липкий» заголовок, а также «липкий» блок в правом нижнем углу для каждого из :

 h1  position: sticky; top: 15px;> .squares__item:last-of-type  position: sticky; bottom: 15px;> h1  position: sticky; top: 15px; > .squares__item:last-of-type  position: sticky; bottom: 15px; >      

Как понять

Скопировать ссылку «Как понять» Скопировано

Блоки с «липким» позиционированием ведут себя как position : relative и position : fixed одновременно. Пока блок не достиг указанного расстояния от края окна браузера, он ведёт себя как относительно спозиционированный. Когда блок достигнет этой точки, то станет вести себя, как будто мы указали position : fixed . А когда он встретится с противоположным краем родителя, то снова будет вести себя, как position : relative .

Как пишется

Скопировать ссылку «Как пишется» Скопировано

 .block  position: sticky; top: 15px;> .block  position: sticky; top: 15px; >      

Для блока, который должен быть «липко» позиционирован, указываем position : sticky и позицию относительно окна браузера. В этом примере блок «прилипнет» на расстоянии 15 пикселей от верхнего края окна.

Подсказки

Скопировать ссылку «Подсказки» Скопировано

�� Если нужный элемент занимает всю высоту родительского блока (если он один в блоке или просто самый высокий среди соседних элементов), то position : sticky не сработает.

�� При вертикальном скролле работают только свойства top и bottom , при горизонтальном — left и right . Или их логические аналоги inset .

�� position : sticky можно указать внутри родителя с overflow : scroll или overflow : auto .

�� Если элементу указать большее число пикселей, чем позволяет родитель, то элемент сразу встанет к противоположному краю родительского блока, но за пределы блока не выйдет.

На практике

Скопировать ссылку «На практике» Скопировано

Лена Райан советует

Скопировать ссылку «Лена Райан советует» Скопировано

�� С помощью такого позиционирования удобно делать закреплённую шапку — если она является непосредственным наследником body , то, указав шапке position : sticky , мы получим статичную шапку при загрузке экрана, а при скролле страницы — зафиксированную сверху.

Как на са­мом деле ра­бо­та­ет position: sticky в CSS

У position: sticky уже очень неплохая браузерная поддержка, но большинство разработчиков так и не используют это свойство.

У этого есть две основные причины: во-первых, браузерам потребовалось много времени на реализацию адекватной поддержки этого свойства. И все просто успели забыть о нём.

Во-вторых, многие разработчики до конца не понимают логику, по которой это свойство работает. И тут появляюсь я!

Я полагаю, что вы хорошо знакомы с позиционированием в CSS, но давайте кратко повторим основные моменты:

Ещё три года назад существовало четыре типа позиционирования: static , relative , absolute и fixed .

Основное различие между static и relative , absolute и fixed в том, какое место они занимают в потоке документа (DOM). Элементы с позицией static и relative сохраняют своё естественное положение в потоке документа, в то время как absolute и fixed «вырываются» из потока документа и становятся плавающими.

Новое значение sticky похоже на все предыдущие значения сразу. Я проиллюстрирую это чуть позже.

Моё первое знакомство с «липким» позиционированием Скопировать ссылку

Думаю, что большинство из вас игрались с «липким» позиционированием. Так было и у меня, пока в один момент я не осознал, что совсем не понимаю это свойство.

При первом знакомстве с position: sticky все быстро понимают, что элемент залипает, когда область просмотра достигает определённой позиции.

.some-component

Проблема в том, что иногда это работает, а иногда нет. Когда всё работает, то элемент и правда залипает. Но когда не работает, то при прокрутке элемент перестаёт залипать. Как человеку, который живёт одним только CSS, мне было важно разобраться в сути проблемы. Именно поэтому я решил тщательно изучить «липкое» позиционирование.

«Липкая» разведка Скопировать ссылку

Во время своих экспериментов я заметил, что если элемент с position: sticky является единственным ребёнком своего родителя-обёртки, то этот «липкий» элемент не залипает.

  .sticky 
Некий контент

Когда я добавлял больше элементов внутрь родителя-обёртки всё начинало работать как ожидалось.

Почему так происходит?

Причина кроется в том, что элемент с position: sticky может перемещаться только в пределах контейнера, в котором находится. А поскольку в моём случае он был единственным ребёнком, у него не было элементов-братьев, поверх которых он мог перемещаться.

Как на самом деле работает position: sticky в CSS Скопировать ссылку

«Липкое» позиционирование состоит из двух основных частей: «липкого» элемента и «липкого» контейнера.

«Липкий» элемент — это элемент, которому мы задали position: sticky . Элемент будет становиться плавающим, как только область видимости достигнет определённой позиции, например top: 0px .

.some-component

«Липкий» контейнер — это HTML-элемент, который оборачивает «липкий» элемент. Это максимальная область, в которой может перемещаться наш элемент.

Когда вы задаёте элементу position: sticky , его родитель автоматически становится «липким» контейнером! Очень важно это запомнить! Контейнер будет являться областью видимости для элемента. «Липкий» элемент не может выйти за пределы своего «липкого» контейнера.

В этом причина, почему в предыдущем примере «липкий» элемент не залипал: он был единственным дочерним элементом контейнера.

В заключение Скопировать ссылку

Вот и всё. Я надеюсь, что вам понравилась эта статья и мне удалось поделиться своим опытом. Я буду признателен, если вы поделитесь этим постом и поаплодируйте.

Другие мои посты о CSS Скопировать ссылку

  • New CSS Logical Properties!
  • Becoming a CSS Grid Ninja!
  • The New Responsive Design Evolution
  • The Best Way to RTL Websites with Sass!
  • CSS Architecture for Multiple Websites With Sass

Почему position: sticky в некоторых случаях не работает?

Почему position: sticky; не срабатывает? Заметил, что в некоторых случаях работает, а в некоторых нет, но не могу понять почему.

.parent < display: block; height: auto; >.left < display: inline-block; width: 200px; height: auto; >.right < display: inline-block; width: 400px; height: 1000px; margin-left: 10px; >.sticky
 
sticky block
right block

Отслеживать
24k 4 4 золотых знака 35 35 серебряных знаков 68 68 бронзовых знаков
задан 3 апр 2019 в 20:25
13 1 1 золотой знак 1 1 серебряный знак 4 4 бронзовых знака

sticky двигается в пределах высоты родительского блока, но у него height: auto и высота в точности равна высоте sticky — двигаться банально негде. Уберите

, и sticky начнёт успешно двигаться по высоте блока parent

3 апр 2019 в 20:49
Или просто растяните left на всю высоту любым доступным способом
3 апр 2019 в 20:57
@andreymal благодарю, проблема действительно в высоте блока left
4 апр 2019 в 21:54

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Элемент позиционируется в соответствии с нормальным потоком документа, а затем смещается относительно его ближайшего прокручивающего предка и содержит containing block (ближайший предка уровня блока), включая элементы, связанные с таблицей, на основе значений top , right , bottom , и left . Смещение не влияет на положение любых других элементов.

Это значение всегда создает новый stacking context. Обратите внимание, что липкий элемент «прилипает» к его ближайшему предшественнику, имеющему «механизм прокрутки» (созданный при overflow от hidden , scroll , auto , или overlay ), даже если тот не является ближайшим фактически прокручивающим предком. Это эффективно препятствует любому «липкому» поведению (см. Github issue on W3C CSSWG).

#example-element-container < width: 350px; >.box < background-color: rgba(0, 0, 255, .2); border: 3px solid #00f; float: left; width: 65px; height: 65px; >.clear < clear: both; padding-top: 1em; >.box+.box < margin-left: 10px; >#example-element < background-color: #ff0; border: 3px solid red; z-index: 1; >#example-element
 

In this demo you can control the position property for the yellow box.

To see the effect of sticky positioning, select the position: sticky option and scroll this container.

The element will scroll along with its container, until it is at the top of the container (or reaches the offset specified in top), and will then stop scrolling, so it stays visible.

The rest of this text is only supplied to make sure the container overflows, so as to enable you to scroll it and see the effect.


Far out in the uncharted backwaters of the unfashionable end of the western spiral arm of the Galaxy lies a small unregarded yellow sun. Orbiting this at a distance of roughly ninety-two million miles is an utterly insignificant little blue green planet whose ape-descended life forms are so amazingly primitive that they still think digital watches are a pretty neat idea.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *