CSS scroll-margin-top

scroll-margin-top is the production-friendly offset for anchor targets hidden under sticky or fixed headers.

Rule

When a page has a sticky or fixed header and uses hash links, set a top scroll margin on headings or other anchor targets:

:root {
  --header-height: 80px;
}

:target,
h2[id],
h3[id] {
  scroll-margin-top: var(--header-height);
}

The property adds an outset to the element's scroll snap area. For hash navigation, that gives the browser room above the target, so the heading lands below the sticky header instead of underneath it. MDN lists scroll-margin-top as widely available since April 2021. Source: MDN, reviewed 2026-07-02

Implementation Notes

  • Prefer a CSS variable tied to the real header height, especially when mobile and desktop headers differ.
  • Apply it to actual anchor targets (:target, [id] headings, generated doc anchors), not to the header.
  • If the header height changes across breakpoints, update --header-height in the same media query or container rule.
  • Test deep links and copy-link-to-heading flows, not only scroll snapping demos.

The reviewed visual artifact shows the before/after clearly: without scroll-margin-top, the fixed header covers the section heading; with scroll-margin-top: 80px, the heading lands visibly below the header. Victor's self-thread also explains the CSS variable variant for variable header heights. Source: X/@vponamariov thread, 2026-03-06


Timeline

  • 2026-03-06 | @vponamariov shared the sticky-header anchor fix: add scroll-margin-top to headings, or use scroll-margin-top: var(--header-height) when header height changes. Source: X/@vponamariov, 2026-03-06
  • 2026-07-02 | Dedicated page created during X bookmark artifact review. Current source checked against MDN; local before/after image preserved as the visual explanation. Source: MDN, 2026-07-02