Detailed explanation
In CSS, position: sticky keeps an element in normal document flow while allowing its visual position to adjust during scrolling. It initially appears where normal layout places it. Once scrolling would move it past an inset such as top: 0, the browser offsets it to preserve that boundary when space permits. Unlike position: fixed, it does not become independently anchored to the viewport or leave a gap that needs a replacement placeholder; its original layout space remains reserved.
Two boundaries control sticky positioning: the nearest ancestor scrollport provides the inset reference, while the containing block limits how far the element can move. With top: 0, a header stays at the top of its relevant scrollport after reaching that edge, but eventually moves away when its containing block ends. If no ancestor establishes a relevant scroll container, the viewport supplies the scrollport. Internally, the browser calculates an allowed sticky region using the scrollport and inset values, then adjusts the element without moving its normal-flow siblings.
For example, .header { position: sticky; top: 0; background: white; z-index: 10; } creates a header that sticks at its scrollport’s top edge. The background prevents underlying content from showing through, and z-index helps control overlap within the surrounding stacking-context hierarchy. Sticky positioning itself creates a stacking context. At least one inset must be non-auto on the axis where sticking is needed; otherwise, sticky behaves like relative positioning on that axis. Logical properties such as inset-block-start can replace physical properties when supporting different writing modes.
An important correction is that overflow: hidden on an ancestor does not categorically disable sticky. It can establish the scroll container used as the reference, even when that ancestor does not scroll through ordinary user interaction, making sticking during page scrolling appear broken. Overflow: auto and scroll can similarly redirect the reference. Also check whether the containing block provides enough travel space and whether flex or grid stretching makes the sticky item too tall. Interviewers expect you to distinguish the scrollport from the containing block, rather than simply describe sticky as switching to fixed.
Key points to remember
- Sticky preserves its normal-flow space while visually shifting during scrolling.
- Set a non-auto inset, such as top: 0, on the axis that should stick.
- The nearest relevant scrollport supplies the inset reference; the containing block limits movement.
- Ancestor overflow can change the scrolling reference rather than universally disable sticky.
- Check available travel space, flex/grid stretching, and stacking contexts when debugging.
Common mistakes candidates make
- Saying sticky literally switches to position: fixed or always sticks to the viewport.
- Forgetting an inset or expecting sticking when the containing block leaves no room for movement.
- Claiming overflow: hidden always breaks sticky without identifying the actual scroll container.
Likely follow-up questions
How is position: sticky different from position: fixed?
Sticky remains in normal flow and is constrained by its containing block. Fixed is removed from normal flow and usually uses the viewport as its containing block, although ancestors with properties such as transform can change that.
How would you debug a sticky header that does not stick?
Verify its computed position and inset, then inspect ancestor overflow to identify the relevant scroll container. Check that this container actually scrolls and that the sticky element has room to move within its containing block.
Can overflow: clip help when overflow: hidden interferes with sticky?
Overflow: clip clips content without itself establishing a scroll container, unlike overflow: hidden. It can therefore preserve a more distant scrolling reference, but verify both axes because their overflow values interact.
Interview tip: Explain sticky using normal flow, a scrollport-relative inset, and a containing-block boundary, then demonstrate the header example.
