I have a fixed header followed by a list with various anchor tags. By default, the anchor will jump to the top of the browser. I need to offset this so it displays below the header.

I found a solution online, but became quite annoyed once I found out that yes it works but only in FF, not webkit.

So if anyone can figure out a nice way to do above that also works with webkit, I'd be so happy. It's one of the last bits of my UI I have left to finish and it's starting to frustrate me.

Dani AI

Generated

A concise summary of what happened in this thread: the fixed header pushes fragment targets under the header (the original issue described). tried the common padding + negative-margin trick, which does make the fragment land below the header but caused section overlap/selection problems. and suggested using a framework like Bootstrap, but this is solvable with a tiny, focused fix.

A modern, CSS-only solution that avoids stacking is to use scroll-margin-top on the elements that are jumped to. It tells the browser to leave that much space when bringing the element into view, so no layout hack is needed and selection/stacking problems do not occur:

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

h2, .anchor-target {
  scroll-margin-top: var(--header-h);
}

If older browsers must be supported, use a targeted pseudo-element fallback that only applies when an element is the active fragment (so other sections do not shift):

:target::before {
  content: "";
  display: block;
  height: var(--header-h);
  margin-top: calc(var(--header-h) * -1);
  visibility: hidden;
}

For dynamic header heights (responsive/toolbars) or if finer control is required, a tiny JS fallback does the jump then nudges the scroll by the header height:

(function(){
  var headerH = 64; // compute on load/resize if needed
  document.addEventListener('click', function(e){
    var a = e.target.closest('a[href^="#"]');
    if(!a) return;
    var id = a.getAttribute('href').slice(1);
    var el = document.getElementById(id);
    if(!el) return;
    e.preventDefault();
    el.scrollIntoView(true);
    window.scrollBy(0, -headerH);
    history.pushState(null, '', '#'+id);
  }, false);
})();

Troubleshooting notes drawn from the thread: confirm id attributes are correct (an id should not include a leading # in HTML — that was present in 's snippet and will cause confusion), pick a reliable header height (or compute it on resize), and prefer scroll-margin-top as the first choice since it avoids the stacking issue entirely.

Recommended Answers

All 4 Replies

Member Avatar for Member #120589

Have a look at Twitter Bootstrap - they have something similar I believe.

Member Avatar for Member #46692

Second that picking up and tweaking a responsive framework like bootstrap is the way to go... I have and I've yet to regret doing so.

I've used one in my CMS platform ignitedcms (github).

You can also find prestyled bootstrap themes on TF for $10 one of them is sure to fit your existing theme with minor tweaks.

http://codecanyon.net/category/skins/bootstrap

Member Avatar for Member #46692

offtopic are you still writing java apps, it's been a while

I'm trying to do this as well. I found that you can set:

section
{
    padding-top: 50px; /* or however the height of your header */
    margin-top: -50px;
}

The negative margin will offset the padding and it will all look correct and the anchor will work. But unfortunately it layers each section to be anchored on top of each other such that the text is no longer selectable when doing something like:

<section id="#a">A</section>
<section id="#b">B</section>
<section id="#c">C</section>
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.