This site has a sticky navbar — the kind that stays pinned to the top of the screen while you scroll. Standard, boring CSS: position: sticky; top: 0;. While building it, I took a screenshot to check how it looked after scrolling down the page, and the navbar was nowhere near the top. It was sitting in the middle of the screenshot, at roughly the same distance down as I'd scrolled — as if it had never stuck to anything at all.

So I "fixed" it. Then fixed it again. Then started doubting whether position: sticky even worked the way I thought it did.

The instinct that wasted the first twenty minutes

My first move was to distrust the CSS. I added transform: translateZ(0) and will-change: transform — the standard incantation for "force this element onto its own compositor layer," which fixes a real, if uncommon, class of Chromium rendering glitches. I took another screenshot. Identical result, down to the byte size of the PNG. That should have been the first clue: an actual rendering fix changing zero pixels usually means the fix was aimed at the wrong layer of the problem entirely.

The question I should have asked first

Eventually I stopped changing CSS and asked a more basic question: is the navbar actually mispositioned, or does it just look that way in this specific screenshot? Those are different bugs with different fixes, and I'd been assuming the answer without checking.

The way to check is to stop looking at pictures and ask the browser directly:

const nav = document.querySelector('.nav');
console.log({
  scrollY: window.scrollY,
  navTop: nav.getBoundingClientRect().top,
  position: getComputedStyle(nav).position,
});
// { scrollY: 1000, navTop: 0, position: "sticky" }

navTop: 0, at every scroll position I tried. According to the browser's own layout engine — not a picture of the browser, the actual engine — the navbar was exactly where it was supposed to be. The bug wasn't in the CSS. It was in whatever was taking the screenshot.

Why that's an uncomfortable thing to find out

A screenshot feels like ground truth. It's a picture of the actual pixels the actual browser actually drew — what could be more authoritative than that? But a screenshot is also just another piece of software, with its own capture pipeline, its own timing assumptions, its own bugs. In my case, it turned out to be a headless rendering environment that intermittently failed to recomposite a stuck sticky element after certain kinds of scroll events — a real, if obscure, limitation of that specific tool, not of the page it was capturing.

I only found that by refusing to trust the picture and going one layer deeper: getBoundingClientRect() is a direct question to the browser's layout engine, and it doesn't go through a screenshot compositor at all. Once the two sources disagreed, one of them had to be wrong, and only one of them was actually measuring the thing I cared about.

The general lesson

"Trust but verify" usually gets applied to code — don't trust that a function works, write a test. It applies just as much to your tools. A debugger, a screenshot, a monitoring dashboard, a log line: each one is a claim about reality, made by software that can itself be wrong, stale, or measuring something slightly different from what you think it's measuring. When two sources of truth disagree, the fix isn't to keep patching based on the one that's easiest to look at. It's to find a third, more direct source — the actual DOM, the actual network request, the actual database row — and let that arbitrate.

In this case, that meant trusting four lines of console output over a stack of screenshots. The navbar was never broken. My belief that the screenshot was accurate was the actual bug, and it was the only one I needed to fix.