How to get sticky elements to stick
Sticky elements are used to persist context to make information easier to understand. They commonly appear in navigation, tables and tooltips. Outside of web development, sticky elements are also widely known as frozen rows or columns, thanks to Excel.
When the CSS position: sticky
property was introduced, many developers thought it would make sticking elements much easier, and it did, for most parts. There are times where it doesn’t, and debugging those scenarios are often an exercise of frustration.
In this tutorial, we will learn what makes sticky elements stick, and how you can debug your stuck element.
How sticky works
First, a sticky element requires a parent container, which is the nearest scrollable container. The parent container defines the boundaries of the sticky element, preventing the element from going beyond the parent container.
Secondly, position: sticky
works as a position: relative
until it crosses a threshold and is treated as a position: fixed
.
.child {
position: sticky;
top: 0;
left: 50px;
}
Debugging sticky
Check element for position offset properties
In order for the sticky element to stick, it needs to act as a position: fixed
element when it passes the threshold, which
requires one of the top
, right
, bottom
, left
properties to be declared.
Check the element’s height
When the sticky element’s height is more than the viewport, to our eyes it looks like sticky stops working at some point. It load looks that way because the element has touched the bottom of the viewport.
.child {
position: sticky;
top: 0;
left: 50px;
height: 120vh;
}
In order to prevent this from happening, either change the height
of the element, or set a max-height
property to ensure it stays within the viewport height.
.child {
position: sticky;
top: 0;
left: 50px;
height: 120vh;
max-height: 100vh;
}
Check parents for overflow
When parent elements of the sticky element have an overflow
property set to hidden
, scroll
or auto
, they become the new scrollable context. When this scrollable context does not scroll, visually it looks like the sticky element has stopped working.
.parent {
overflow: visible;
height: auto;
}
.child {
position: sticky;
top: 0;
left: 50px;
}
There are three ways to resolve this:
- Set the
overflow
property tovisible
. - Give the parent element a
height
. - Set the
overflow
property toclip
. (Limited browser support. Only Chrome 90 supports this at time of writing.)
If all else fails
If the above steps do not work for you, perhaps you have reached the limits of what position: sticky
can do for you. JavaScript solutions may be required and there are plenty of well tested libraries to try out.
Alternatively, you could take on the challenge of writing your own by changing CSS styles with the use of an IntersectionObserver.