Skip to content
Carl Victor Fontanos
Carl Victor Fontanos

Carl Victor Fontanos

Software Engineer

I build web applications and share what I learn along the way.

© 2026

Anchor Links Hiding Under Your Fixed Header? scroll-margin-top

C
Carlo Fontanos
· 2 min read

Click a table-of-contents link, the page jumps, and the section heading you wanted is buried under the sticky navbar. You scroll up 70 pixels by hand, slightly annoyed. Multiply that by every documentation site built since sticky headers became standard.

The historical fixes were all bad: invisible padding-top with negative margins (breaks backgrounds and click targets), JavaScript scroll interception (janky, fights the browser), or offset anchor spans littered through the markup. The actual fix:

h2, h3, [id] {
    scroll-margin-top: 80px;   /* your header height + breathing room */
}

scroll-margin-top tells the browser: when scrolling this element into view - anchor jumps, :target navigation, focus scrolling, scrollIntoView() calls - leave this much space above it. It affects nothing else. No layout change, no visual change, just corrected scroll destinations.

Make it track the real header height

Hardcoded 80px rots when the header changes. Tie them together with a custom property:

:root { --header-h: 64px; }

.site-header { height: var(--header-h); }

:is(h2, h3, h4)[id], [id].anchor {
    scroll-margin-top: calc(var(--header-h) + 16px);
}

The two companions worth adding

Smooth scrolling, respectfully:

@media (prefers-reduced-motion: no-preference) {
    html { scroll-behavior: smooth; }
}

Wrapping it in the media query means users who've asked their OS for less motion get instant jumps - more on why that matters.

Highlight the target section so people see where they landed:

:target {
    animation: flash 1.2s ease-out;
}

@keyframes flash {
    from { background: #fef3c7; }
    to   { background: transparent; }
}

:target matches the element whose id is in the URL fragment - a selector from 2008 that pairs beautifully with a property from 2020.

Support

scroll-margin has been in every browser since 2019-2020 (it started life in the scroll-snap spec as snap margins, which is why it also fine-tunes carousel snap points). There is genuinely no reason left to have broken anchor links on a modern site - it's three declarations, total.

C
Written by Carlo Fontanos

Full-stack web developer sharing practical tutorials and building tools that ship.

Got something on your mind?

My inbox is open - no forms disappearing into the void here.

  • Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
  • Hire me for a project Have something custom in mind? Let's talk scope and timelines.
  • Product support Bought something here? I'll help you get it running.

I usually reply within 1-2 business days.

Message sent!

Your details are only used to reply to you.

Keep reading