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

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

  • автор:

Как на самом деле работает 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

В заключении

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

position:sticky is not working

.header has a height of 150px. .navbar has a height of 20px. When the user scrolls, I want .navbar to stick at the top. So I went to the CSS and set position:sticky and top:0. But this didn’t work. I initially thought that firefox is not supporting position:sticky, but that’s not the case because I was able to see a working demo of it. I googled about it but found nothing helpful. Anyone knows why this is not working?

Wolfuryo's user avatar

12 Answers 12

Position sticky was not working for me due to the body element having overflow-x: hidden; set.

isherwood's user avatar

The 2 most common culprits why position: sticky; might not work are:

  1. You haven’t defined top: 0; , bottom: 0; , left: 0 or something similar
  2. One of the parents of your sticky element has overflow (x or y) set to hidden , scroll or auto .

For me it was the first one.

Dimitris Siakavelis's user avatar

It works fine if you move the navbar outside the header. See below. For the reason, according to MDN:

The element is positioned according to the normal flow of the document, and then offset relative to its flow root and containing block based on the values of top, right, bottom, and left.

For the containing block:

The containing block is the ancestor to which the element is relatively positioned

So, when I do not misunderstand, the navbar is positioned at offset 0 within the header as soon as it is scrolled outside the viewport (which, clearly, means, you can’t see it anymore).

isherwood's user avatar

SVSchmidt's user avatar

To expand from the answers above and some information to make it work with flexbox parent and overflow other than visible (the examples below assume you use vertical — sticky with either top or bottom set to a certain value and position set to sticky):

The most frequent case is you have an ancestor element (not just immediate parent) with overflow property set to something other than visible and as a result there is no space is left to stick around. To quickly find out if this is the case, you can run this script in the browser console (please make sure you change the .your-sticky-element class to your element’s selector):

SOLUTION:

a) If you found there is overflow set, and you can remove it, this should solve it

b) If you have to keep your overflow setting, you have to make the parent element’s height higher than the sticky element’s height. If the parent element has no height or the sticky element fills up all the height, it means there is simply no place to stick within when the page is scrolled. It doesn’t need to an explicit height (vertical), but you can inspect to see if your sticky element has extra space left after itself.

Parent is not higher than the sticky element to leave extra space. This particular case can be caused by different circumstances but the solution to this is the same above, please see 1.b

If your sticky element’s parent is a flexbox (align-items has default value of normal) or grid, and if the sticky element itself doesn’t have a proper align-self set, there will be no space left for the sticky element to hold when scrolling (for example, if it is align-self: stretch or auto [default value]). This is because the child element is stretched to fill up the height of the parent.

SOLUTION:

In this case, align-self: flex-start set for the sticky element can fix the problem because in the element will stand at the start, leaving extra space after itself.

Guide: There are much more complex circumstances both in the case of flexboxes and without it, but the general rule of thumb is your sticky element needs space within the parent to be sticky when scrolled.

How to Fix Issues With CSS Position Sticky Not Working?

Learn possible reasons why CSS position sticky might not be working for you

  • Daniyal Hamid
  • 26 Jan, 2022
  • 3 min read

There could be a number of reasons why the CSS position: sticky property might not be working for you. You can check the following list of things to fix some common / potential issues with using it:

Checking for Browser Compatibility

Before you check for other issues, it might be a good idea to ensure that you’re using a browser that supports position: sticky .

Checking if a Threshold Has Been Specified

A sticky element requires a threshold to be specified, which means that you must set a value other than » auto » for at least one of the following properties:

  • top
  • right
  • bottom
  • left

This threshold value that you set, would make the sticky element act as fixed positioned when it crosses the specified threshold, and a relatively positioned element otherwise.

Checking Vendor Prefix for Safari

Make sure you add a vendor prefix for the property value to support versions of Safari below 13, for example, like so:

Checking if an Ancestor Element Has overflow Property Set

If any parent/ancestor of the sticky element has any of the following overflow properties set, position: sticky won’t work (unless you specify a height on the overflowing container):

  1. overflow: hidden
  2. overflow: scroll
  3. overflow: auto

Snippet to Check for Parents With overflow Property Set:

Simply copy/paste the following snippet in your browser’s web developer console to identify all parent elements with overflow property set to something other than visible :

How to Make position: sticky Work With the overflow Property?

By specifying a height on the overflowing container, you should be able to make position: sticky work whilst having the container element have the overflow property set.

Checking if height Property Is Not Set on Parent

If the parent element has no height set then the sticky element won’t have any area to stick to when scrolling. This happens because the sticky element is meant to stick/scroll within the height of a container.

Checking if a Parent Element Is a Flexbox

If sticky element’s parent is a flexbox, there are two scenarios to check for:

  1. The sticky element has align-self: auto set (which is the default);
  2. The sticky element has align-self: stretch set.

If the Sticky Element Has align-self: auto Set:

In this case the value of align-self would compute to the parent’s align-items value. So, if the parent has align-items: normal (which is the default) or align-items: stretch set, then it means the height of the sticky element would stretch to fill the entire available space. This would leave no room for the sticky element to scroll within the parent.

If the Sticky Element Has align-self: stretch Set:

In this case, the sticky element would stretch to the height of the parent, and would not have any area to scroll within.

How to Make Sticky Element Scrollable Within a Flexbox:

You could simply set the value of the align-self property to align-self: flex-start . This would put the sticky element at the start and won’t stretch it.

Hope you found this post useful. It was published 26 Apr, 2020 (and was last revised 26 Jan, 2022 ). Please show your love and support by sharing this post.

Fixing CSS position sticky not working issues

Position:sticky CSS property is commonly used to create sticky headers or footers. We will go over a few problems and solutions when using this property.

Nov 30, 2022 | Read time 7 minutes

�� Table of contents

You are not specifying at least one of the CSS properties: top , left , right or bottom . Be careful though if you specify more than one of those. If both left and right are specified, left wins. Likewise, if top and bottom are used at the same time, top wins — Based on this bug

Internet Explorer, Edge 15 and earlier versions do not support sticky positioning

The parent element does not have it height or position:relative specified. This would need to apply to all parent elements of the sticky element and not just the immediate ancestor.

The parent element, such as a div is using the flex display. We need to also set the sticky element to have align-self: flex-start .

What is the position:sticky anyway?

Elements that are defined with position sticky are positioned normally based on the document flow. It will then “stick” with its nearest parent element’s scroll behaviour.

Below is a demo of how it should behave:

We can lay it out as follows:

Check if using position:sticky with flex

When the parent element of a position sticky element is set as flex display, this will not work unless you have set the right CSS properties.

Consider the following HTML and CSS, we have the main element as display:flex and we want to make the child yellow element sticky

This results in the above — we can see that the yellow element is not sticking at all. It just takes the height of the main element.

Since flex box elements default to stretch , all the elements are the same height — which does not allow scrolling and thus the sticky behaviour would not kick in.

Adding align-self: flex-start to the sticky element set the height to auto, which allowed scrolling will fix it. The align-self: flex-start property overrides the flex item’s align-items value. In this case we use flex-start which put the flex item at the start of the parent.

Check Position:sticky with overflow (hidden, scroll or auto)

On the parent of the sticky element, AVOID using overflow:hidden , overflow:scroll , or overflow:auto .

Since sticky elements rely on the scrolling of the parent element — modifying overflow behaviour will break this.

However using overflow:visible or overflow:clip should be fine to keep your sticky elements desired behaviour.

Safari browser support for position:sticky

Support for position:sticky is widespread for most of the modern browsers (Chrome, Firefox, Edge, etc) however there are some cases we will need to consider. For Safari browsers, its best to use the vendor prefixes (-webkit-sticky):

  • No support for IE 11 or lower versions
  • Supported on th elements, but not thead or tr in Edge/Chrome
  • Do not appear to support sticky table headers

The Javascript (old method)

We can use Javascript to mimic the same behaviour as position:sticky . This can be handy when you want to support older browsers such as IE or older versions of Safari.

The idea is to have a event listener on the scroll. As the user moves out of the viewport (scroll down), we apply a position:fixed to that element we want to stick.

As the user scrolls up and goes back into the view, we remove the position:fixed styling.

This method is not prefered since it can make your page look janky since processing is done on the CPU side.

Using the default position sticky will shift process to the GPU (Graphical Processing Unit) and will appear more smooth.

Summary

  • check the top, left, right and bottom is set,
  • check the browser support — or use JavaScript if you want to support legacy browsers such as IE
  • check that the parent is using flex or not — if flex is used, then the sticky element needs to have align-self:flex-start
  • Make sure you are NOT using any overflow properties on the parent.

�� About the Author

G’day! I am Kentaro a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember ��)

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

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