ScreenshotNeo

BlogHow-to

Fix Website Screenshots with Text Hidden Behind Sticky Navigation

Fix headings hidden by sticky navigation with the right scroll offset, then diagnose whether the issue comes from page layout or screenshot capture.

By the ScreenshotNeo team4 October 20266 min read

If a screenshot shows a heading tucked behind sticky navigation, first check the page at the same viewport size and scroll position. For anchor links or programmatic scrolling, reserve the navigation’s measured height on the element that actually scrolls with scroll-padding-top, or set scroll-margin-top on the affected targets. If the text is still covered in a screenshot taken without scrolling to an anchor, investigate the layout and the capture mode separately.

A sticky element behaves like a relatively positioned element until it reaches its configured threshold, then stays at that offset while its scroll container permits. Content can pass beneath it. Sticky positioning is tied to the nearest ancestor with a scrolling mechanism, and needs a threshold such as top to take effect. See MDN’s positioning guide and Chrome’s sticky positioning overview.

1. Reproduce the screenshot state

  1. Record the screenshot viewport width and height, page URL, scroll position, and whether it is a viewport or full-page capture.
  2. Load the same URL in a browser at that viewport. Reproduce any banner dismissal, menu state, font loading, or other page state relevant to the capture.
  3. Check whether the text is covered in the browser too. If it is, inspect the layout and scrolling behavior. If it appears only in the screenshot, compare the capture tool’s viewport and full-page behavior with the browser rendering; the cause cannot be assigned to a particular screenshot tool without testing that tool.
  4. Identify the navigation’s effective height at that viewport. Include every stacked bar that overlaps the content, such as a top announcement bar plus the main navigation.
  5. Find the actual scroll container. The document may scroll, or a nested panel may scroll instead.

2. Fix anchor targets with scroll-padding-top

Use scroll-padding-top when the scroll container should reserve an inset for its scroll targets. For document scrolling, put it on the root scrolling element:

:root {
  --site-nav-height: 4rem; /* Replace with the measured effective height. */
}

html {
  scroll-padding-top: var(--site-nav-height);
}

This gives the browser a top inset when it scrolls targets into view, including targets reached through in-page links. The offset must match the actual navigation height; 4rem is only an example. MDN’s scroll-padding-top reference describes reserving space in the optimal viewing region, and its scroll-padding guide includes a fixed-header example.

If a nested element scrolls, apply the property to that element instead:

.article-panel {
  max-height: 70vh;
  overflow: auto;
  scroll-padding-top: var(--site-nav-height);
}

Do not put the offset on html by habit if a nested panel is the element performing the scroll. Sticky positioning and scroll offsets depend on the relevant scrolling ancestor.

3. Use scroll-margin-top for selected targets

If only certain headings need an offset, set scroll-margin-top on those targets:

:root {
  --site-nav-height: 4rem;
}

.article-section h2[id],
.article-section h3[id] {
  scroll-margin-top: var(--site-nav-height);
}

scroll-margin-top changes the target’s scroll area outset. It is useful when a subset of targets should land below the navigation, while other targets should use the container’s default alignment. See MDN’s scroll-margin-top reference.

Choose one approach first so the landing position is easy to predict. You can combine container padding and target margin when their cumulative effect is intentional, but applying both the same full header height can leave more space than expected.

4. Check sticky positioning and layout

Scroll offsets fix where scrolling places a target. They do not fix every case of content being obscured. Check these conditions if text remains hidden:

  • Sticky threshold: confirm the navigation has a threshold such as top: 0. Without an inset threshold, sticky positioning does not take effect as expected.
  • Scroll ancestor: inspect ancestors for overflow: auto, scroll, or hidden. Sticky positioning is tied to the nearest ancestor with a scrolling mechanism, which may not be the viewport.
  • Stacked bars: measure the combined occupied height, not just the primary navigation.
  • Responsive changes: check the offset at every supported breakpoint. A wrapped or condensed navigation can change its height.
  • Content layout: if the first content is covered on initial page load, consider adding appropriate content padding or correcting the layout. Scroll padding only affects the optimal viewing region during scrolling.
  • Capture type: compare viewport and full-page results. The available evidence does not establish how any particular screenshot product handles sticky elements during full-page capture.

5. Verify the fix

  1. At each relevant viewport, measure the visible navigation height.
  2. Follow every in-page link whose destination was obscured.
  3. Repeat for direct navigation to a URL containing a fragment, such as /guide#installation.
  4. Test keyboard navigation and programmatic scrolling if the page uses them.
  5. Capture the same browser state and compare viewport and full-page screenshots.
  6. Check that the offset does not leave an unnecessarily large gap when the navigation is collapsed or absent.

6. Troubleshooting

Symptom Likely cause What to do
Anchor heading still lands behind the bar The offset is on the wrong scrolling element, or its value is too small. Find the element that actually scrolls and apply the offset there. Measure the combined overlapping bar height at the affected viewport.
Heading lands too far below the bar Both container padding and target margin may be adding space, or the measured height is too large. Start with one offset strategy, then tune it using the rendered navigation height.
CSS works for some sections but not others Some targets may be in a different scroll container or may not match the target selector. Inspect the target DOM and its scrolling ancestor. Confirm the target has the expected ID or class.
Sticky navigation stops sticking early or never sticks An ancestor’s scrolling mechanism or the sticky element’s containing block constrains it. Inspect ancestor overflow and the sticky threshold. Verify which element scrolls before changing offsets.
Only the full-page screenshot looks wrong The capture result may differ from the browser’s viewport rendering, or the page state may differ. Reproduce the same viewport and page state in a browser, then check the screenshot tool’s documentation and compare capture modes. Do not assume a CSS fix until the browser shows the same issue.
Offset breaks at a mobile breakpoint The navigation height changes with wrapping, collapsed controls, or responsive styles. Set a breakpoint-specific custom property or otherwise derive the offset from the actual layout at each breakpoint.

7. Performance, reliability, and cost

These CSS properties are layout and scrolling configuration; they do not require a screenshot service. Keep the offset tied to the real navigation height and test the viewport sizes and scroll containers your page uses. For automated screenshot workflows, make the viewport and page state reproducible so a changed header height or capture mode can be distinguished from an actual content regression. No prevalence rate or tool-specific full-page behavior is established by the sources cited here.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its API returns a screenshot from one GET request. See the API documentation for options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners are accepted and removed before the shot; newsletter popups and chat widgets are removed too. Each cleanup step can be turned off.
  • Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Responses identify the page verdict and billing status in headers.
  • An MCP server gives AI agents tools for screenshots, page information, and PDF capture.
  • The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

Sign up for 1,000 free screenshots a month, with no card.

FAQ

Should I put the offset on the header?

Usually, no. Put scroll-padding-top on the scrolling container or scroll-margin-top on the target whose landing position needs adjustment.

Does scroll-padding-top move the page content down on initial load?

It reserves an inset for the scroll container’s optimal viewing region. If content is covered before any scrolling, inspect the page layout and consider content spacing separately.

Sticky content can remain at its threshold while other content moves beneath it. Check the layout, the actual scrolling ancestor, and whether the screenshot reproduces the browser state.

Is the full-page screenshot tool definitely at fault?

No conclusion follows from the screenshot alone. Compare the same page state in a browser and consult the documentation for the specific capture tool.