The CSS position: sticky
may not work for a number of reasons. You can consider the following checklist to address potential issues:
- Check for Browser Compatibility;
- Check if a Threshold Has Been Specified;
- Check if Parent or Ancestor Element Has
overflow
Property Set; - Check if Sticky Has Enough Room to Scroll Within;
- Check if the Sticky Element Stretches Inside a Flexbox;
- Check for Overriding Rules.
Checking for Browser Compatibility
Check that the browser you're using supports position: sticky
.
Known Issues
-
Missing Vendor Prefix For Safari 13 and Below
In Safari 13 and below, a vendor prefix (
-webkit-sticky
) is required in addition toposition: sticky
:.sticky { position: -webkit-sticky; position: sticky; top: 0; }
-
Sticky Table Headers Issue
Firefox 58 & below, Chrome 63 & below and Safari 7 & below do not appear to support sticky table headers:
div { width: 500px; height: 75px; overflow: auto; } table { width: 100%; border-collapse: collapse; table-layout: fixed; } thead { color: #fff; position: sticky; top: 0; background-color: #444; } tbody { height: 50px; } tbody td { border: 1px solid #ccc; }
Check if a Threshold Has Been Specified
A sticky element requires a threshold to be specified for properties like top
, right
, bottom
, and left
. The threshold value that you set, will make the sticky element act as fixed positioned when it crosses the specified threshold, and a relatively positioned element otherwise. You can see in action in the following example:
#sticky
top: 0
Failure to set a threshold can make the sticky element behave similarly to relative positioning:
#sticky
top: auto
Therefore, you must set a value other than "auto
" for at least one of, top
, right
, bottom
, or left
properties for position: sticky
to work. For example:
.sticky { position: sticky; top: 0; }
Check if Parent or Ancestor Element Has overflow
Property Set
If a parent or ancestor of the sticky element has overflow: hidden
, overflow: scroll
, or overflow: auto
, the sticky might not work. You can see this issue in the following example:
has
extra
text
to
stretch
the
container
#sticky
To diagnose and fix this issue, you can do the following:
-
Find Parent or Ancestors With
overflow
Property SetYou can copy/paste the following snippet in your browser's web developer console to identify all parent/ancestor elements with
overflow
property set to something other thanvisible
:let parent = document.querySelector('.sticky').parentElement; while (parent) { const hasOverflow = getComputedStyle(parent).overflow; if (hasOverflow !== 'visible') { console.log(hasOverflow, parent); } parent = parent.parentElement; }
-
Add a
height
for the Overflowing ContainerBy specifying a height on the overflowing container(s) you identified in the previous step, you should be able to make
position: sticky
work without having to remove theoverflow
property from the container element.Consider, for example, the following where setting the
height
on the overflowing element (e.g., "#parent
") fixes the issue:#parent { height: 100px; overflow: auto; } #parent > div { display: inline-block; vertical-align: top; } #sticky { position: sticky; top: 0; }
For detailed explanation and examples, check out the post about fixing CSS position: sticky
not working with overflow.
Checking if Sticky Has Enough Room to Scroll Within
If the sticky element does not have enough room to scroll within, it won't work. This could be the case when:
-
Sticky Element Has Same or Larger Height Than the Parent
#parent { display: inline-block; } #parent > div { height: 200px; } #sticky { position: sticky; top: 0; }
This will make all children of "
#parent
" (including the sticky element) the sameheight
, producing an output like the following:One
height: 200px
Two
height: 200px
position: sticky
height: 200px
-
Sticky Element Is Stretched to Same Height as Parent
#parent { display: inline-block; height: 200px; } #sticky { height: 200px; position: sticky; top: 0; }
This will make the sticky and the parent element the same
height
, producing an output like the following:One
height: auto
Two
height: auto
position: sticky
height: 200px
In these cases the sticky element ends up having no room for scrolling within its container. Therefore, to make the sticky work in these instances, you can make the height
of the sticky smaller, or make the height
of the parent larger. For example:
#parent { display: inline-block; } #parent > div { height: 200px; } #sticky { height: 60px !important; position: sticky; top: 0; }
This will make the height
of the sticky element smaller than its siblings, giving it room inside its container to stick within:
height: 200px
height: 200px
position: sticky
height: 60px
As a rule of thumb, the parent element should always have a larger height than the sticky element for it to work.
Checking if the Sticky Element Stretches Inside a Flexbox
If sticky element's parent is a flexbox, then you must make sure that it does not stretch to occupy the entire height of its container. Otherwise, it will leave no room for it to move within. This can be the case in the following scenarios:
-
Parent Has
align-items: normal
and Sticky Hasalign-self: auto
#parent { display: flex; gap: 5px; /* align-items: normal; */ } #sticky { /* align-self: auto; */ position: sticky; top: 0; }
The flex parent and sticky element default to
align-items: normal
andalign-self: auto
respectively. So, when you implicitly or explicitly specify these values,position: sticky
won't work:OneTwo
has
extra
text
to
stretch
the
container#sticky
align-self: auto
-
Parent Has
align-items: stretch
and Sticky Hasalign-self: auto
#parent { display: flex; gap: 5px; align-items: stretch; } #sticky { /* align-self: auto; */ position: sticky; top: 0; }
When the flex parent explicitly has
align-items: stretch
and the sticky element implicitly or explicitly hasalign-self: auto
set,position: sticky
won't work:OneTwo
has
extra
text
to
stretch
the
container#sticky
align-self: auto
-
When Sticky Has
align-self: stretch
#parent { display: flex; gap: 5px; align-items: center; } #sticky { align-self: stretch; position: sticky; top: 0; }
When the sticky element is has
align-self: stretch
set, it takes precedence over parent'salign-items
value, resulting in the sticky element being stretched to fill the container. This leaves no room for sticky to scroll within:OneTwo#sticky
align-self: stretch
To fix all these issues, you can simply set the value of the align-self
property of the sticky element to a value that does not make it stretch. For example, you could set align-self
to flex-start
, making the sticky element position at the start and not be stretched:
#sticky
align-self: flex-start
For detailed explanation and examples, check out the post about fixing CSS position: sticky
not working in a flexbox.
Checking for Overriding Rules
You can make sure that the element you are applying the position: sticky
property to is not being overridden by a more specific selector.
For example, consider the following HTML/CSS:
<div id="parent"> <div id="child-1">Foo</div> <div id="child-2">Bar</div> </div>
#child-1 { position: sticky; top: 0; }
It could be the case, for example, that another CSS selector with higher specificity is overriding your selector and the CSS style rules on the element, such as the following:
#parent #child-1 { position: relative; }
To fix this, you can either remove the more specific selector, or make your selector more specific than the other one.
This post was published (and was last revised ) by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.