An HTML element with CSS position: sticky applied might not work in a flexbox layout for the following reasons:
- Sticky Element Has Same or Larger Height Than Parent;
- Sticky Element Is Stretched to Same Height As Parent;
- No Threshold Is Specified;
- Overflowing Parent or Ancestor Doesn't Have Height.
If neither of these help you solve your issue, then you might want to check for browser compatibility and other common issues.
Sticky Element Has Same or Larger Height Than Parent
Problem
If the sticky element's height is explicitly (or implicitly) set to an equal or larger value than its parent, then the sticky element ends up having no room for scrolling within its container. For example:
#parent { display: flex; gap: 5px; }
#parent > div { height: 200px; }
#sticky { position: sticky; top: 0; }
This will make all flex items the same height, producing an output like the following:
height: 200pxheight: 200pxposition: stickyheight: 200pxAs you can see in this example, the sticky has no place to move within as it occupies the entire height of its container.
Solution
To make the sticky element stick to its container in this instance, you can do either of the following:
- Make the height of the sticky smaller, or;
- Make the height of the parent larger.
With either of the changes, the idea is to make room for the sticky element to move within. For example, you can make the height of the sticky element smaller than its parent when all flex items are explicitly set to the same height:
#parent { display: flex; gap: 5px; }
#parent > div { height: 200px; }
#sticky { height: 60px !important; position: sticky; top: 0; }
With these changes, the output will be like the following:
height: 200pxheight: 200pxposition: stickyheight: 60pxSticky Element Is Stretched to Same Height As Parent
Problem
Whenever the sticky element is stretched, it will occupy the entire height of its container, leaving no room for it to move within. This can be the case in the following scenarios:
#parent |
#sticky |
Description |
|---|---|---|
align-items: normal(default) |
align-self: auto(default) |
These default values are implicitly set, and behave as stretch in a flexbox. |
align-items: stretch |
align-self: auto(default) |
All flex items will compute to the parent's align-items value, and end up being enlarged to fill the container. |
align-items: ... /* any value */ |
align-self: stretch |
align-self takes precedence, and consequently, the sticky item is stretched to fill the container. |
You can see the result of applying these combinations in the following examples:
-
When both, parent and sticky elements have the default value (i.e.,
align-items: normalandalign-self: autorespectively), the sticky element is stretched:#parent
align-items: normalOneTwo
has
extra
text
to
stretch
the
container#sticky
align-self: autoIn this case,
align-items: normalandalign-self: autoare implicitly set if no other value is specified (as they're both default values):#parent { display: flex; gap: 5px; /* align-items: normal; */ } #sticky { /* align-self: auto; */ position: sticky; top: 0; }You can also explicitly set these values and have the same result:
#parent { display: flex; gap: 5px; align-items: normal; } #sticky { align-self: auto; position: sticky; top: 0; } -
When the parent and the sticky element have
align-items: stretchandalign-self: autorespectively, then all flex items will compute to the parent'salign-itemsvalue, and end up being stretched to fill the container:#parent
align-items: stretchOneTwo
has
extra
text
to
stretch
the
container#sticky
align-self: autoIn this case,
align-self: autois the default value for flex items, and is implicitly set if no other value is specified:#parent { display: flex; gap: 5px; align-items: stretch; } #sticky { /* align-self: auto; */ position: sticky; top: 0; }You can also explicitly set flex items to
align-self: autoto the same effect:#parent { display: flex; gap: 5px; align-items: stretch; } #sticky { align-self: auto; position: sticky; top: 0; } -
When the sticky element has
align-self: stretch, it takes precedence over parent'salign-itemsvalue, resulting in the sticky element being stretched to fill the container, like so:#parent
align-items: center
height: 200pxOneTwo#sticky
align-self: stretchFor example:
#parent { display: flex; gap: 5px; align-items: center; } #sticky { align-self: stretch; position: sticky; top: 0; }
Solution
In these cases, you need to make sure the sticky element is not stretched, i.e.:
- It has a value other than
align-self: stretch, or; - When it is set to
align-self: auto(default), the parent is not set toalign-items: normal(default), oralign-items: stretch.
To fix issues with the previously shown stretched sticky elements, you can, for example, simply set align-self: start on the sticky elements to make them appear at the start and avoid them from being stretched:
-
#parent
align-items: normalOneTwo
has
extra
text
to
stretch
the
container#sticky
align-self: start -
#parent
align-items: stretchOneTwo
has
extra
text
to
stretch
the
container#sticky
align-self: start -
#parent
align-items: center
height: 200pxOneTwo#sticky
align-self: start
No Threshold Is Specified
Problem
To ensure proper behavior in sticky positioning, you need to define a threshold to a value other than "auto" using at least one of the following: top, right, bottom, or left.
If a threshold isn't specified for the sticky element, its behavior becomes indistinguishable from relative positioning, as you can see in the following example:
#stickytop: autoSolution
If you specify a threshold, for example, by setting top to a value other than auto, then the sticky will flow within its container till it meets the opposite edge of its containing block:
#stickytop: 10pxOverflowing Parent or Ancestor Doesn't Have Height
Problem
The sticky element won't move within its parent if the parent or any of its ancestors compute to an overflow property other than overflow: visible — i.e., one of the following:
overflow: hiddenoverflow: scrolloverflow: auto
For example:
#parentoverflow: autohas
extra
text
to
stretch
the
container
#stickyalign-self: start
Learn more about why position: sticky does not work with the CSS overflow property and how to fix it.
Solution
In such a case, you must specify a height on the overflowing container, which in this case is the parent of the sticky element:
#parentheight: 100pxoverflow: autohas
extra
text
to
stretch
the
container
#stickyalign-self: startThis 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.