position: sticky is a mix of relative and fixed. The element sits in the normal flow until you scroll to a set distance from the edge, then it sticks there. It stays inside its parent, so when the parent ends, the element leaves with it.
<style>
body { margin: 0; }
.sticky-head { position: sticky; top: 0; background: #d94a00; color: #fff; padding: 8px 12px; }
section { height: 180px; padding: 10px; }
</style>
<section>Scroll down in the Result panel…</section>
<div class="sticky-head">I stick to the top once you reach me</div>
<section>More content</section>
<section style="background:#f4f9fc">More content</section>
The one rule: you need an offset
Sticky does nothing without a threshold such as top: 0 (or bottom, left, right). That value says where to stick.
Good uses
- A table header row that stays visible in a long table.
- A table of contents or filter panel in a sidebar that follows you.
- Section headings in a long list.
Why it sometimes does not work
- No offset. Add
top: 0. - An ancestor has
overflowset tohidden,autoorscroll. That makes the ancestor the scroll container and the element sticks to it, not the page. This is the most common cause. - The parent is too short. The element can only travel inside its parent. If the parent is exactly as tall as the element, there is nothing to scroll through.
- In a flex row, the item stretched to the full height of the row. Add
align-self: flex-startso the element is shorter than its parent.
Fixed or sticky?
sticky when you want the element to start in its natural place and then follow. Use fixed when it should always be at a screen position.