position: sticky fails in a very specific way: the element looks normal, the CSS looks valid, and nothing sticks. Developers often reach for z-index, but layering only matters after sticky positioning has activated. Most sticky bugs are scroll-container bugs.
A sticky element is evaluated inside the nearest relevant scrolling context and constrained by its containing block. If an ancestor unexpectedly creates a scroll container, or if the parent is too short, the sticky element may never reach the behavior you expected.
Confirm the basic contract
Start with the simple requirements. The element needs position: sticky and an offset.
.section-nav {
position: sticky;
inset-block-start: 1rem;
}
Without an inset, the browser has no threshold. If the element has an offset and still does not stick, inspect the ancestors.
Walk up overflow ancestors
Any ancestor with overflow that creates a scroll container can change sticky behavior. The common accidental pattern is a large wrapper with clipping:
.page {
overflow: hidden;
}
That rule may have been added to hide a decorative bleed or horizontal overflow. It can also trap sticky descendants. The better fix is usually to contain the specific decorative or overflowing element instead of clipping the whole page.
Look for overflow: hidden, overflow: auto, overflow: scroll, and sometimes overflow: clip. Also inspect axis-specific overflow. A wrapper meant to control horizontal overflow can still affect how descendants behave if it creates a new formatting or scrolling context.
Check parent height
Sticky elements are constrained by their containing block. If the parent ends immediately after the sticky element, the element has no long region to stick within. This often happens when a sticky sidebar is placed inside a short wrapper next to a much taller article.
.article-layout {
display: grid;
grid-template-columns: minmax(0, 1fr) 16rem;
align-items: start;
}
.article-sidebar {
position: sticky;
inset-block-start: 1rem;
}
Make sure the grid parent spans the article content, not just the sidebar. Use outlines during debugging so you can see the sticky element’s parent boundary. If the sticky element reaches the parent’s end almost immediately, the browser is doing the correct thing.
Watch Grid and Flex stretching
Grid and Flexbox can stretch items by default. A stretched sidebar can become as tall as the row, which may remove the visual space needed for sticky movement. Setting align-items: start on the grid or align-self: start on the sticky item often makes the layout easier to reason about.
Do not apply that fix blindly. If stretching was needed for equal-height backgrounds or borders, move that visual treatment to a wrapper and let the sticky item itself keep a natural height.
Account for fixed headers
If the page has a fixed or sticky site header, the sticky offset should include enough space below it. Otherwise the sticky element may work but sit underneath the header.
:root {
--site-header-block: 4rem;
}
.section-nav {
position: sticky;
inset-block-start: calc(var(--site-header-block) + 1rem);
}
Use a shared variable only when the relationship is real and stable. If one page has a different header treatment, keep the offset local to that layout.
The debugging move
Confirm the offset, then inspect ancestors for overflow, containment, transforms, and unexpected height boundaries. Outline the sticky element, its parent, and the suspected scroll container. Scroll slowly and watch which box the sticky element is constrained by.
Only after sticky activates should you debug layering. If the element sticks but appears under content, then inspect stacking contexts and z-index. If it never sticks, z-index is noise.
Test the result at the smallest viewport where the sticky behavior remains enabled. A sidebar that works on a tall desktop can become taller than the viewport on a short laptop, especially when browser chrome, zoom, or long navigation labels are involved. Add max-block-size and internal scrolling only when the sticky content truly needs to remain available.
Finally, question whether sticky is still useful on narrow screens. Many sticky sidebars should become normal content below the article header. Sticky is a progressive enhancement, not a requirement for the page to make sense. If disabling sticky improves reading space and focus order on mobile, that is usually the better responsive behavior.
Document the scroll owner when the layout is shared. A short comment near the wrapper can prevent the next overflow fix from breaking sticky behavior again.