position: fixed removes an element from the scroll flow entirely and pins it in place always; position: sticky is a hybrid — it stays in its normal spot until scrolling passes that point, then locks. That's why a sticky header flows normally at the top of the page and only sticks once you've scrolled past it.
You need exactly three things: position: sticky, a top: 0 (the point it sticks to), and no overflow: hidden on any ancestor — that silently breaks sticky entirely. Watch z-index too, or content beneath can render above the header.
Hide-on-scroll-down, show-on-scroll-up headers need more than sticky alone — you listen to the scroll event and drive transform: translateY yourself.
When to use
Use it for controls users need throughout a scroll — navigation, search, filters. On small mobile screens, keep it short so it doesn't eat too much of the viewport.